diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -2,6 +2,16 @@
 =====================
 
 
+v1.0.16 (February 2024)
+-----------------------
+
+* No changes in the main API
+
+* `Data.Fixtures`: support more types in existing functions
+
+* `Data.Fixtures`: add `filter'`, `drop'`, `take'`, `foldr'`, `ff2`, `ff3`, ...
+
+
 v1.0.14 (January 2024)
 ----------------------
 
diff --git a/express.cabal b/express.cabal
--- a/express.cabal
+++ b/express.cabal
@@ -1,6 +1,6 @@
 -- Cabal file for express
 name: express
-version: 1.0.14
+version: 1.0.16
 synopsis: Dynamically-typed expressions involving function application and variables.
 description:
   Express is a library for manipulating dynamically typed Haskell expressions.
@@ -62,7 +62,7 @@
 source-repository this
   type:           git
   location:       https://github.com/rudymatela/express
-  tag:            v1.0.14
+  tag:            v1.0.16
 
 library
   exposed-modules:     Data.Express
diff --git a/src/Data/Express/Fixtures.hs b/src/Data/Express/Fixtures.hs
--- a/src/Data/Express/Fixtures.hs
+++ b/src/Data/Express/Fixtures.hs
@@ -137,6 +137,7 @@
   , gg, ggE
   , hh, hhE
   , oo, ooE
+  , ff2, ff3, ff4
   , question
   , (-?-)
   , (-$-)
@@ -176,6 +177,8 @@
   , elem'
   , sort'
   , insert'
+  , drop'
+  , take'
   , bs_, pps, qqs
   , and', or'
   , sum', product'
@@ -206,6 +209,8 @@
   , mapE
   , (-.-)
   , map'
+  , foldr'
+  , filter'
 
   -- ** Enum
   , enumFrom',   (-..)
@@ -554,7 +559,8 @@
 minusTwo :: Expr
 minusTwo  =  val (-2 :: Int)
 
--- | A variable function @f@ of 'Int -> Int' type lifted over the 'Expr' type.
+-- | A variable function @f@ of 'a -> a' type lifted over the 'Expr' type.
+--   This works for 'Int', 'Bool', 'Char' and their lists
 --
 -- > > ff xx
 -- > f x :: Int
@@ -562,7 +568,15 @@
 -- > > ff one
 -- > f 1 :: Int
 ff :: Expr -> Expr
-ff  =  (ffE :$)
+ff  =  mk1 "ff"
+  [ var "f" (undefined :: F Int)
+  , var "f" (undefined :: F Bool)
+  , var "f" (undefined :: F Char)
+  , var "f" (undefined :: F [Int])
+  , var "f" (undefined :: F [Bool])
+  , var "f" (undefined :: F String)
+  ]
+type F a  =  a -> a
 
 -- | A variable @f@ of 'Int -> Int' type encoded as an 'Expr'.
 --
@@ -571,7 +585,8 @@
 ffE :: Expr
 ffE  =  var "f" (undefined :: Int -> Int)
 
--- | A variable function @g@ of 'Int -> Int' type lifted over the 'Expr' type.
+-- | A variable function @g@ of 'a -> a' type lifted over the 'Expr' type.
+--   This works for 'Int', 'Bool', 'Char' and their lists.
 --
 -- > > gg yy
 -- > g y :: Int
@@ -579,7 +594,14 @@
 -- > > gg minusTwo
 -- > gg (-2) :: Int
 gg :: Expr -> Expr
-gg  =  (ggE :$)
+gg  =  mk1 "gg"
+  [ var "g" (undefined :: F Int)
+  , var "g" (undefined :: F Bool)
+  , var "g" (undefined :: F Char)
+  , var "g" (undefined :: F [Int])
+  , var "g" (undefined :: F [Bool])
+  , var "g" (undefined :: F String)
+  ]
 
 -- | A variable @g@ of 'Int -> Int' type encoded as an 'Expr'.
 --
@@ -593,7 +615,14 @@
 -- > > hh zz
 -- > h z :: Int
 hh :: Expr -> Expr
-hh  =  (hhE :$)
+hh  =  mk1 "hh"
+  [ var "h" (undefined :: F Int)
+  , var "h" (undefined :: F Bool)
+  , var "h" (undefined :: F Char)
+  , var "h" (undefined :: F [Int])
+  , var "h" (undefined :: F [Bool])
+  , var "h" (undefined :: F String)
+  ]
 
 -- | A variable @h@ of 'Int -> Int' type encoded as an 'Expr'.
 --
@@ -602,24 +631,95 @@
 hhE :: Expr
 hhE  =  var "h" (undefined :: Int -> Int)
 
-mk1 :: String -> [Expr] -> Expr -> Expr
-mk1 nm efs ex  =  headOr (err nm efs [ex]) $ efs >$$ ex
-
-mk2 :: String -> [Expr] -> Expr -> Expr -> Expr
-mk2 nm efs ex ey  =  headOr (err nm efs [ex,ey]) $ efs >$$ ex >$$ ey
-
-mk3 :: String -> [Expr] -> Expr -> Expr -> Expr -> Expr
-mk3 nm efs ex ey ez  =  headOr (err nm efs [ex,ey,ez]) $ efs >$$ ex >$$ ey >$$ ez
+-- | A variable function @f@ of 'a -> a -> a' type lifted over the 'Expr' type.
+--   This works for 'Int', 'Bool', 'Char' and their lists
+--
+-- > > ff2 xx yy
+-- > f x y :: Int
+--
+-- > > ff2 one two
+-- > f 1 2 :: Int
+--
+-- The result type is bound to the type of the last argument.
+ff2 :: Expr -> Expr -> Expr
+ff2  =  mk2 "ff2"
+  [ var "f" (undefined :: F21 Int)
+  , var "f" (undefined :: F21 Bool)
+  , var "f" (undefined :: F21 Char)
+  , var "f" (undefined :: F21 [Int])
+  , var "f" (undefined :: F21 [Bool])
+  , var "f" (undefined :: F21 String)
+  , var "f" (undefined :: F2 Int [Int])
+  , var "f" (undefined :: F2 Bool [Bool])
+  , var "f" (undefined :: F2 Char [Char])
+  , var "f" (undefined :: F2 [Int] Int)
+  , var "f" (undefined :: F2 [Bool] Bool)
+  , var "f" (undefined :: F2 [Char] Char)
+  , var "f" (undefined :: F2 Int Bool)
+  , var "f" (undefined :: F2 Bool Int)
+  ]
+type F2 a b  =  a -> b -> b
+type F21 a  =  F2 a a
 
-mk4 :: String -> [Expr] -> Expr -> Expr -> Expr -> Expr -> Expr
-mk4 nm efs ex ey ez ew  =  headOr (err nm efs [ex,ey,ez,ew]) $ efs >$$ ex >$$ ey >$$ ez >$$ ew
+-- | A variable function @f@ of 'a -> a -> a -> a' type lifted over the 'Expr' type.
+--   This works for 'Int', 'Bool', 'Char' and their lists
+--
+-- > > ff3 xx yy zz
+-- > f x y z :: Int
+--
+-- > > ff3 one two three
+-- > f 1 2 3 :: Int
+--
+-- The result type is bound to the type of the last argument.
+ff3 :: Expr -> Expr -> Expr -> Expr
+ff3  =  mk3 "ff3"
+  [ var "f" (undefined :: F31 Int)
+  , var "f" (undefined :: F31 Bool)
+  , var "f" (undefined :: F31 Char)
+  , var "f" (undefined :: F31 [Int])
+  , var "f" (undefined :: F31 [Bool])
+  , var "f" (undefined :: F31 String)
+  , var "f" (undefined :: F3 Int Int [Int])
+  , var "f" (undefined :: F3 Int [Int] Int)
+  , var "f" (undefined :: F3 [Int] Int Int)
+  , var "f" (undefined :: F3 Int [Int] [Int])
+  , var "f" (undefined :: F3 [Int] Int [Int])
+  , var "f" (undefined :: F3 [Int] [Int] Int)
+  ]
+type F3 a b c  =  a -> b -> c -> c
+type F31 a  =  F3 a a a
 
-err :: String -> [Expr] -> [Expr] -> Expr
-err fn efs exs  =  error
-                $  fn ++ ": unhandled type: "
-                ++ intercalate ", " (map show exs)
-                ++ "\n    accepted types are:\n"
-                ++ unlines (map (("    " ++) . show) efs)
+-- | A variable function @f@ of 'a -> a -> a -> a -> a' type lifted over the 'Expr' type.
+--   This works for 'Int', 'Bool', 'Char' and their lists
+--
+-- > > ff3 xx yy zz xx'
+-- > f x y z xx' :: Int
+--
+-- > > ff3 one two three four
+-- > f 1 2 3 4 :: Int
+--
+-- The result type is bound to the type of the last argument.
+ff4 :: Expr -> Expr -> Expr -> Expr -> Expr
+ff4  =  mk4 "ff4"
+  [ var "f" (undefined :: F41 Int)
+  , var "f" (undefined :: F41 Bool)
+  , var "f" (undefined :: F41 Char)
+  , var "f" (undefined :: F41 [Int])
+  , var "f" (undefined :: F41 [Bool])
+  , var "f" (undefined :: F41 String)
+  , var "f" (undefined :: F4 Int Int Int [Int])
+  , var "f" (undefined :: F4 Int Int [Int] Int)
+  , var "f" (undefined :: F4 Int [Int] Int Int)
+  , var "f" (undefined :: F4 [Int] Int Int Int)
+  , var "f" (undefined :: F4 Int [Int] [Int] [Int])
+  , var "f" (undefined :: F4 [Int] Int [Int] [Int])
+  , var "f" (undefined :: F4 [Int] [Int] Int [Int])
+  , var "f" (undefined :: F4 [Int] [Int] [Int] Int)
+  , var "f" (undefined :: F4 Int Int [Int] [Int])
+  , var "f" (undefined :: F4 [Int] [Int] Int Int)
+  ]
+type F4 a b c d  =  a -> b -> c -> d -> d
+type F41 a  =  F4 a a a a
 
 -- | A variable binary operator @?@ lifted over the 'Expr' type.
 --   Works for 'Int', 'Bool', 'Char', @[Int]@ and 'String'.
@@ -1144,6 +1244,7 @@
 nilInt   =  val ([] :: [Int])
 nilBool  =  val ([] :: [Bool])
 nilChar  =  value "[]" ([] :: [Char])
+nilInts  =  val ([] :: [[Int]])
 
 -- | The list constructor with 'Int' as element type encoded as an 'Expr'.
 --
@@ -1175,9 +1276,11 @@
 unit :: Expr -> Expr
 unit e  =  e -:- nil'
   where
-  nil' | typ e == typ i_  =  nil
+  nil' | typ e == typ i_  =  nilInt
        | typ e == typ c_  =  emptyString
        | typ e == typ b_  =  nilBool
+       | typ e == typ is_  =  nilInts
+       | otherwise  =  err "unit" [e] [nil,emptyString,nilBool,nilInts]
 
 -- | The list constructor lifted over the 'Expr' type.
 --   Works for the element types 'Int', 'Char' and 'Bool'.
@@ -1195,7 +1298,14 @@
   [ consInt
   , consBool
   , consChar
+  , value ":" ((:) :: Cons [Int])
+  , value ":" ((:) :: Cons [Bool])
+  , value ":" ((:) :: Cons String)
+  , value ":" ((:) :: Cons (Int,Int))
+  , value ":" ((:) :: Cons (Bool,Bool))
+  , value ":" ((:) :: Cons (Char,Char))
   , value ":" ((:) :: Cons (Maybe Int))
+  , value ":" ((:) :: Cons (Either Int Int))
   ]
 infixr 5 -:-
 
@@ -1213,11 +1323,17 @@
 -- > "bc" -++- "c" :: [Char]
 (-++-) :: Expr -> Expr -> Expr
 (-++-)  =  mk2 "(-++-)"
-  [ value "++" ((++) :: [Int] -> [Int] -> [Int])
-  , value "++" ((++) :: String -> String -> String)
-  , value "++" ((++) :: [Bool] -> [Bool] -> [Bool])
+  [ value "++" ((++) :: Append Int)
+  , value "++" ((++) :: Append Char)
+  , value "++" ((++) :: Append Bool)
+  , value "++" ((++) :: Append [Int])
+  , value "++" ((++) :: Append [Char])
+  , value "++" ((++) :: Append [Bool])
+  , value "++" ((++) :: Append (Int,Int))
+  , value "++" ((++) :: Append (Maybe Int))
   ]
 infixr 5 -++-
+type Append a  =  [a] -> [a] -> [a]
 
 -- | List 'head' lifted over the 'Expr' type.
 --   Works for the element types 'Int', 'Char' and 'Bool'.
@@ -1235,10 +1351,16 @@
 -- > 1
 head' :: Expr -> Expr
 head'  =  mk1 "head'"
-  [ value "head" (head :: [Int] -> Int)
-  , value "head" (head :: [Char] -> Char)
-  , value "head" (head :: [Bool] -> Bool)
+  [ value "head" (head :: Head Int)
+  , value "head" (head :: Head Char)
+  , value "head" (head :: Head Bool)
+  , value "head" (head :: Head [Int])
+  , value "head" (head :: Head [Char])
+  , value "head" (head :: Head [Bool])
+  , value "head" (head :: Head (Int,Int))
+  , value "head" (head :: Head (Maybe Int))
   ]
+type Head a  =  [a] -> a
 
 -- | List 'tail' lifted over the 'Expr' type.
 --   Works for the element types 'Int', 'Char' and 'Bool'.
@@ -1256,10 +1378,16 @@
 -- > [2]
 tail' :: Expr -> Expr
 tail'  =  mk1 "tail'"
-  [ value "tail" (tail :: [Int] -> [Int])
-  , value "tail" (tail :: [Char] -> [Char])
-  , value "tail" (tail :: [Bool] -> [Bool])
+  [ value "tail" (tail :: Tail Int)
+  , value "tail" (tail :: Tail Char)
+  , value "tail" (tail :: Tail Bool)
+  , value "tail" (tail :: Tail [Int])
+  , value "tail" (tail :: Tail [Char])
+  , value "tail" (tail :: Tail [Bool])
+  , value "tail" (tail :: Tail (Int,Int))
+  , value "tail" (tail :: Tail (Maybe Int))
   ]
+type Tail a  =  [a] -> [a]
 
 -- | List 'null' lifted over the 'Expr' type.
 --   Works for the element types 'Int', 'Char' and 'Bool'.
@@ -1274,10 +1402,16 @@
 -- > True
 null' :: Expr -> Expr
 null'  =  mk1 "null'"
-  [ value "null" (null :: [Int] -> Bool)
-  , value "null" (null :: [Char] -> Bool)
-  , value "null" (null :: [Bool] -> Bool)
+  [ value "null" (null :: Null Int)
+  , value "null" (null :: Null Char)
+  , value "null" (null :: Null Bool)
+  , value "null" (null :: Null [Int])
+  , value "null" (null :: Null [Char])
+  , value "null" (null :: Null [Bool])
+  , value "null" (null :: Null (Int,Int))
+  , value "null" (null :: Null (Maybe Int))
   ]
+type Null a  =  [a] -> Bool
 
 -- | List 'length' lifted over the 'Expr' type.
 --   Works for the element types 'Int', 'Char' and 'Bool'.
@@ -1295,10 +1429,16 @@
 -- > 1
 length' :: Expr -> Expr
 length'  =  mk1 "length'"
-  [ value "length" (length :: [Int] -> Int)
-  , value "length" (length :: [Char] -> Int)
-  , value "length" (length :: [Bool] -> Int)
+  [ value "length" (length :: Length Int)
+  , value "length" (length :: Length Char)
+  , value "length" (length :: Length Bool)
+  , value "length" (length :: Length [Int])
+  , value "length" (length :: Length [Char])
+  , value "length" (length :: Length [Bool])
+  , value "length" (length :: Length (Int,Int))
+  , value "length" (length :: Length (Maybe Int))
   ]
+type Length a  =  [a] -> Int
 
 -- | List 'init' lifted over the 'Expr' type.
 --   Works for the element types 'Int', 'Char' and 'Bool'.
@@ -1316,10 +1456,16 @@
 -- > [0]
 init' :: Expr -> Expr
 init'  =  mk1 "init'"
-  [ value "init" (init :: [Int] -> [Int])
-  , value "init" (init :: [Char] -> [Char])
-  , value "init" (init :: [Bool] -> [Bool])
+  [ value "init" (init :: Init Int)
+  , value "init" (init :: Init Char)
+  , value "init" (init :: Init Bool)
+  , value "init" (init :: Init [Int])
+  , value "init" (init :: Init [Char])
+  , value "init" (init :: Init [Bool])
+  , value "init" (init :: Init (Int,Int))
+  , value "init" (init :: Init (Maybe Int))
   ]
+type Init a  =  Tail a
 
 -- | List 'sort' lifted over the 'Expr' type.
 --   Works for the element types 'Int', 'Char' and 'Bool'.
@@ -1337,10 +1483,16 @@
 -- > [1,2]
 sort' :: Expr -> Expr
 sort'  =  mk1 "sort'"
-  [ value "sort" (sort :: [Int] -> [Int])
-  , value "sort" (sort :: [Char] -> [Char])
-  , value "sort" (sort :: [Bool] -> [Bool])
+  [ value "sort" (sort :: Sort Int)
+  , value "sort" (sort :: Sort Char)
+  , value "sort" (sort :: Sort Bool)
+  , value "sort" (sort :: Sort [Int])
+  , value "sort" (sort :: Sort [Char])
+  , value "sort" (sort :: Sort [Bool])
+  , value "sort" (sort :: Sort (Int,Int))
+  , value "sort" (sort :: Sort (Maybe Int))
   ]
+type Sort a  =  Tail a
 
 -- | List 'insert' lifted over the 'Expr' type.
 --   Works for the element types 'Int', 'Char' and 'Bool'.
@@ -1352,10 +1504,16 @@
 -- > insert False [False,True] :: [Bool]
 insert' :: Expr -> Expr -> Expr
 insert'  =  mk2 "insert'"
-  [ value "insert" (insert :: Int -> [Int] -> [Int])
-  , value "insert" (insert :: Bool -> [Bool] -> [Bool])
-  , value "insert" (insert :: Char -> String -> String)
+  [ value "insert" (insert :: Insert Int)
+  , value "insert" (insert :: Insert Char)
+  , value "insert" (insert :: Insert Bool)
+  , value "insert" (insert :: Insert [Int])
+  , value "insert" (insert :: Insert [Char])
+  , value "insert" (insert :: Insert [Bool])
+  , value "insert" (insert :: Insert (Int,Int))
+  , value "insert" (insert :: Insert (Maybe Int))
   ]
+type Insert a  =  Cons a
 
 -- | List 'elem' lifted over the 'Expr' type.
 --   Works for the element types 'Int', 'Char' and 'Bool'.
@@ -1367,11 +1525,59 @@
 -- > True
 elem' :: Expr -> Expr -> Expr
 elem'  =  mk2 "elem'"
-  [ value "elem" (elem :: Int -> [Int] -> Bool)
-  , value "elem" (elem :: Bool -> [Bool] -> Bool)
-  , value "elem" (elem :: Char -> String -> Bool)
+  [ value "elem" (elem :: Elem Int)
+  , value "elem" (elem :: Elem Char)
+  , value "elem" (elem :: Elem Bool)
+  , value "elem" (elem :: Elem [Int])
+  , value "elem" (elem :: Elem [Char])
+  , value "elem" (elem :: Elem [Bool])
+  , value "elem" (elem :: Elem (Int,Int))
+  , value "elem" (elem :: Elem (Maybe Int))
   ]
+type Elem a  =  a -> [a] -> Bool
 
+-- | List 'drop' lifted over the 'Expr' type.
+--   Works for the element types 'Int', 'Char' and 'Bool'.
+--
+-- > > drop' zero nilInt
+-- > drop 0 [] :: [Int]
+--
+-- > > drop' one (false -:- unit true)
+-- > drop 1 [False,True] :: [Bool]
+drop' :: Expr -> Expr -> Expr
+drop'  =  mk2 "drop'"
+  [ value "drop" (drop :: Drop Int)
+  , value "drop" (drop :: Drop Char)
+  , value "drop" (drop :: Drop Bool)
+  , value "drop" (drop :: Drop [Int])
+  , value "drop" (drop :: Drop [Char])
+  , value "drop" (drop :: Drop [Bool])
+  , value "drop" (drop :: Drop (Int,Int))
+  , value "drop" (drop :: Drop (Maybe Int))
+  ]
+type Drop a  =  Int -> [a] -> [a]
+
+-- | List 'take' lifted over the 'Expr' type.
+--   Works for the element types 'Int', 'Char' and 'Bool'.
+--
+-- > > take' zero nilInt
+-- > take 0 [] :: [Int]
+--
+-- > > take' one (false -:- unit true)
+-- > take 1 [False,True] :: [Bool]
+take' :: Expr -> Expr -> Expr
+take'  =  mk2 "take'"
+  [ value "take" (take :: Take Int)
+  , value "take" (take :: Take Char)
+  , value "take" (take :: Take Bool)
+  , value "take" (take :: Take [Int])
+  , value "take" (take :: Take [Char])
+  , value "take" (take :: Take [Bool])
+  , value "take" (take :: Take (Int,Int))
+  , value "take" (take :: Take (Maybe Int))
+  ]
+type Take a  =  Int -> [a] -> [a]
+
 -- | '$' lifted over 'Expr's
 --
 -- > > absE -$- one
@@ -1386,6 +1592,10 @@
   , value "$" (($) :: Apply [Int])
   , value "$" (($) :: Apply [Bool])
   , value "$" (($) :: Apply [Char])
+  , value "$" (($) :: Apply (Int,Int))
+  , value "$" (($) :: Apply (Bool,Bool))
+  , value "$" (($) :: Apply (Char,Char))
+  , value "$" (($) :: Apply (Maybe Int))
   ]
 infixl 6 -$-
 type Apply a  =  (a -> a) -> a -> a
@@ -1408,6 +1618,14 @@
   , value "==" ((==) :: Comparison [Int])
   , value "==" ((==) :: Comparison [Bool])
   , value "==" ((==) :: Comparison [Char])
+  , value "==" ((==) :: Comparison [[Int]])
+  , value "==" ((==) :: Comparison [[Bool]])
+  , value "==" ((==) :: Comparison [[Char]])
+  , value "==" ((==) :: Comparison (Int,Int))
+  , value "==" ((==) :: Comparison (Bool,Bool))
+  , value "==" ((==) :: Comparison (Char,Char))
+  , value "==" ((==) :: Comparison (Maybe Int))
+  , value "==" ((==) :: Comparison (Int,Int,Int))
   ]
 infix 4 -==-
 type Comparison a  =  a -> a -> Bool
@@ -1428,6 +1646,14 @@
   , value "/=" ((/=) :: Comparison [Int])
   , value "/=" ((/=) :: Comparison [Bool])
   , value "/=" ((/=) :: Comparison [Char])
+  , value "/=" ((/=) :: Comparison [[Int]])
+  , value "/=" ((/=) :: Comparison [[Bool]])
+  , value "/=" ((/=) :: Comparison [[Char]])
+  , value "/=" ((/=) :: Comparison (Int,Int))
+  , value "/=" ((/=) :: Comparison (Bool,Bool))
+  , value "/=" ((/=) :: Comparison (Char,Char))
+  , value "/=" ((/=) :: Comparison (Maybe Int))
+  , value "/=" ((/=) :: Comparison (Int,Int,Int))
   ]
 infix 4 -/=-
 
@@ -1447,6 +1673,14 @@
   , value "<=" ((<=) :: Comparison [Int])
   , value "<=" ((<=) :: Comparison [Bool])
   , value "<=" ((<=) :: Comparison [Char])
+  , value "<=" ((<=) :: Comparison [[Int]])
+  , value "<=" ((<=) :: Comparison [[Bool]])
+  , value "<=" ((<=) :: Comparison [[Char]])
+  , value "<=" ((<=) :: Comparison (Int,Int))
+  , value "<=" ((<=) :: Comparison (Bool,Bool))
+  , value "<=" ((<=) :: Comparison (Char,Char))
+  , value "<=" ((<=) :: Comparison (Maybe Int))
+  , value "<=" ((<=) :: Comparison (Int,Int,Int))
   ]
 infix 4 -<=-
 
@@ -1466,6 +1700,14 @@
   , value "<" ((<) :: Comparison [Int])
   , value "<" ((<) :: Comparison [Bool])
   , value "<" ((<) :: Comparison [Char])
+  , value "<" ((<) :: Comparison [[Int]])
+  , value "<" ((<) :: Comparison [[Bool]])
+  , value "<" ((<) :: Comparison [[Char]])
+  , value "<" ((<) :: Comparison (Int,Int))
+  , value "<" ((<) :: Comparison (Bool,Bool))
+  , value "<" ((<) :: Comparison (Char,Char))
+  , value "<" ((<) :: Comparison (Maybe Int))
+  , value "<" ((<) :: Comparison (Int,Int,Int))
   ]
 infix 4 -<-
 
@@ -1493,6 +1735,9 @@
   , value "if" (iff :: If [Int])
   , value "if" (iff :: If [Bool])
   , value "if" (iff :: If [Char])
+  , value "if" (iff :: If [[Int]])
+  , value "if" (iff :: If [[Bool]])
+  , value "if" (iff :: If [[Char]])
   ]
   where
   iff :: Bool -> a -> a -> a
@@ -1585,6 +1830,9 @@
   , value "compare" (compare :: Compare [Int])
   , value "compare" (compare :: Compare [Bool])
   , value "compare" (compare :: Compare [Char])
+  , value "compare" (compare :: Compare [[Int]])
+  , value "compare" (compare :: Compare [[Bool]])
+  , value "compare" (compare :: Compare [[Char]])
   ]
 type Compare a  =  a -> a -> Ordering
 
@@ -1612,7 +1860,8 @@
 
 -- | The 'Just' constructor lifted over the 'Expr' type.
 --
--- This works for the 'Bool' and 'Int' argument types.
+-- This works for the 'Bool', 'Int', 'Char' argument types
+-- and their lists.
 --
 -- > > just zero
 -- > Just 0 :: Maybe Int
@@ -1622,24 +1871,60 @@
 just  =  mk1 "just"
   [ justInt
   , justBool
+  , value "Just" (Just :: Just Char)
+  , value "Just" (Just :: Just [Int])
+  , value "Just" (Just :: Just [Bool])
+  , value "Just" (Just :: Just String)
   ]
+type Just a  =  a -> Maybe a
 
 -- | An infix synonym of 'pair'.
+--
+-- > > zero -|- xxs
+-- (0,xs) :: (Int,[Int])
+--
+-- > > ae -|- (bee -:- unit cee)
+-- > ('a',"bc") :: (Char,[Char])
 (-|-) :: Expr -> Expr -> Expr
 (-|-)  =  pair
 
 -- | The pair constructor lifted over 'Expr's.
 --
--- This works for the 'Int' and 'Bool' element types
--- by differently from 'foldPair' by returning a well-typed expression.
+-- This works for some variations of 'Int', 'Bool' and 'Char' element types
+-- and their lists.
+--
+-- > > pair zero xxs
+-- (0,xs) :: (Int,[Int])
+--
+-- Differently from 'foldPair', when this works,-
+-- it always constructs a well-typed expression.
 pair :: Expr -> Expr -> Expr
 pair  =  mk2 "pair"
-  [ value "," ((,) :: Pair Int Int)
+  [ value "," ((,) :: Pair1 Int)
+  , value "," ((,) :: Pair1 Bool)
+  , value "," ((,) :: Pair1 Char)
+  , value "," ((,) :: Pair1 [Int])
+  , value "," ((,) :: Pair1 [Bool])
+  , value "," ((,) :: Pair1 [Char])
+  , value "," ((,) :: Pair Int [Int])
+  , value "," ((,) :: Pair Bool [Bool])
+  , value "," ((,) :: Pair Char [Char])
+  , value "," ((,) :: Pair [Int] Int)
+  , value "," ((,) :: Pair [Bool] Bool)
+  , value "," ((,) :: Pair [Char] Char)
   , value "," ((,) :: Pair Int Bool)
   , value "," ((,) :: Pair Bool Int)
-  , value "," ((,) :: Pair Bool Bool)
+  , value "," ((,) :: Pair Int Char)
+  , value "," ((,) :: Pair Char Int)
+  , value "," ((,) :: Pair Int (Int,Int))
+  , value "," ((,) :: Pair (Int,Int) Int)
+  , value "," ((,) :: Pair1 (Int,Int))
+  , value "," ((,) :: Pair1 [[Int]])
+  , value "," ((,) :: Pair1 [[Bool]])
+  , value "," ((,) :: Pair1 [[Char]])
   ]
 type Pair a b  =  a -> b -> (a,b)
+type Pair1 a  =  Pair a a
 
 -- | The pair constructor (@ :: ... -> (Int,Int) @) encoded as an 'Expr'.
 comma :: Expr
@@ -1647,35 +1932,79 @@
 
 -- | The triple/trio constructor lifted over 'Expr's.
 --
--- This only works for the 'Int' element type.
+-- This works for some combinations
+-- of the 'Int', 'Bool' and 'Char' element types
+-- and their lists.
 triple :: Expr -> Expr -> Expr -> Expr
-triple e1 e2 e3  =  ccE :$ e1 :$ e2 :$ e3
-  where
-  ccE  =  value ",," ((,,) :: Int -> Int -> Int -> (Int,Int,Int))
+triple  =  mk3 "triple"
+  [ value ",," ((,,) :: Trio1 Int)
+  , value ",," ((,,) :: Trio1 Bool)
+  , value ",," ((,,) :: Trio1 Char)
+  , value ",," ((,,) :: Trio1 [Int])
+  , value ",," ((,,) :: Trio1 [Bool])
+  , value ",," ((,,) :: Trio1 [Char])
+  , value ",," ((,,) :: Trio Int Int [Int])
+  , value ",," ((,,) :: Trio Int [Int] Int)
+  , value ",," ((,,) :: Trio [Int] Int Int)
+  , value ",," ((,,) :: Trio Int [Int] [Int])
+  , value ",," ((,,) :: Trio [Int] Int [Int])
+  , value ",," ((,,) :: Trio [Int] [Int] Int)
+  , value ",," ((,,) :: Trio Int Int Bool)
+  , value ",," ((,,) :: Trio Int Bool Int)
+  , value ",," ((,,) :: Trio Bool Int Int)
+  , value ",," ((,,) :: Trio Int Bool Bool)
+  , value ",," ((,,) :: Trio Bool Int Bool)
+  , value ",," ((,,) :: Trio Bool Bool Int)
+  ]
+type Trio a b c  =  a -> b -> c -> (a,b,c)
+type Trio1 a  =  Trio a a a
 
 -- | The quadruple constructor lifted over 'Expr's.
 --
--- This only works for the 'Int' element type.
+-- This works for some combinations
+-- of the 'Int', 'Bool' and 'Char' element types
+-- and their lists.
 quadruple :: Expr -> Expr -> Expr -> Expr -> Expr
-quadruple e1 e2 e3 e4  =  cccE :$ e1 :$ e2 :$ e3 :$ e4
-  where
-  cccE  =  value ",,," ((,,,) :: Int -> Int -> Int -> Int -> (Int,Int,Int,Int))
+quadruple  =  mk4 "quadruple"
+  [ value ",,," ((,,,) :: Quartet1 Int)
+  , value ",,," ((,,,) :: Quartet1 Bool)
+  , value ",,," ((,,,) :: Quartet1 Char)
+  , value ",,," ((,,,) :: Quartet1 [Int])
+  , value ",,," ((,,,) :: Quartet1 [Bool])
+  , value ",,," ((,,,) :: Quartet1 [Char])
+  ]
+type Quartet a b c d  =  a -> b -> c -> d -> (a,b,c,d)
+type Quartet1 a  =  Quartet a a a a
 
 -- | The quintuple constructor lifted over 'Expr's.
 --
 -- This only works for the 'Int' element type.
 quintuple :: Expr -> Expr -> Expr -> Expr -> Expr -> Expr
-quintuple e1 e2 e3 e4 e5  =  ccccE :$ e1 :$ e2 :$ e3 :$ e4 :$ e5
-  where
-  ccccE  =  value ",,,," ((,,,,) :: Int -> Int -> Int -> Int -> Int -> (Int,Int,Int,Int,Int))
+quintuple  =  mk5 "quintuple"
+  [ value ",,,," ((,,,,) :: Quintet1 Int)
+  , value ",,,," ((,,,,) :: Quintet1 Bool)
+  , value ",,,," ((,,,,) :: Quintet1 Char)
+  , value ",,,," ((,,,,) :: Quintet1 [Int])
+  , value ",,,," ((,,,,) :: Quintet1 [Bool])
+  , value ",,,," ((,,,,) :: Quintet1 [Char])
+  ]
+type Quintet a b c d e  =  a -> b -> c -> d -> e -> (a,b,c,d,e)
+type Quintet1 a  =  Quintet a a a a a
 
 -- | The sixtuple constructor lifted over 'Expr's.
 --
 -- This only works for the 'Int' element type.
 sixtuple :: Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr
-sixtuple e1 e2 e3 e4 e5 e6  =  cccccE :$ e1 :$ e2 :$ e3 :$ e4 :$ e5 :$ e6
-  where
-  cccccE  =  value ",,,,," ((,,,,,) :: Int -> Int -> Int -> Int -> Int -> Int -> (Int,Int,Int,Int,Int,Int))
+sixtuple  =  mk6 "sixtuple"
+  [ value ",,,,," ((,,,,,) :: Sextet1 Int)
+  , value ",,,,," ((,,,,,) :: Sextet1 Bool)
+  , value ",,,,," ((,,,,,) :: Sextet1 Char)
+  , value ",,,,," ((,,,,,) :: Sextet1 [Int])
+  , value ",,,,," ((,,,,,) :: Sextet1 [Bool])
+  , value ",,,,," ((,,,,,) :: Sextet1 [Char])
+  ]
+type Sextet a b c d e f  =  a -> b -> c -> d -> e -> f -> (a,b,c,d,e,f)
+type Sextet1 a  =  Sextet a a a a a a
 
 -- | A typed hole of @[Bool]@ type encoded as an 'Expr'.
 --
@@ -1810,6 +2139,45 @@
   ]
 type Map a  =  (a -> a) -> [a] -> [a]
 
+
+-- | 'foldr' lifted over 'Expr's.
+--
+-- > > foldr' plus zero (unit one)
+-- > foldr (+) zero [1] :: [Int]
+foldr' :: Expr -> Expr -> Expr -> Expr
+foldr'  =  mk3 "foldr'"
+  [ value "foldr" (foldr :: Foldr1 ())
+  , value "foldr" (foldr :: Foldr1 Int)
+  , value "foldr" (foldr :: Foldr1 Bool)
+  , value "foldr" (foldr :: Foldr1 Char)
+  , value "foldr" (foldr :: Foldr1 [Int])
+  , value "foldr" (foldr :: Foldr1 [Bool])
+  , value "foldr" (foldr :: Foldr1 [Char])
+  , value "foldr" (foldr :: Foldr Int [Int])
+  , value "foldr" (foldr :: Foldr Bool [Bool])
+  , value "foldr" (foldr :: Foldr Char [Char])
+  ]
+type Foldr a b  =  (a -> b -> b) -> b -> [a] -> b
+type Foldr1 a  =  Foldr a a
+
+
+-- | 'filter' lifted over 'Expr's.
+--
+-- > > filter' absE (unit one)
+-- > filter odd [1] :: [Int]
+filter' :: Expr -> Expr -> Expr
+filter'  =  mk2 "filter'"
+  [ value "filter" (filter :: Filter ())
+  , value "filter" (filter :: Filter Int)
+  , value "filter" (filter :: Filter Bool)
+  , value "filter" (filter :: Filter Char)
+  , value "filter" (filter :: Filter [Int])
+  , value "filter" (filter :: Filter [Bool])
+  , value "filter" (filter :: Filter [Char])
+  ]
+type Filter a  =  (a -> Bool) -> [a] -> [a]
+
+
 -- | 'enumFrom' lifted over 'Expr's.
 --
 -- > > enumFrom' zero
@@ -1911,3 +2279,32 @@
       , value ",.." (enumFromThenTo :: EnumFromThenTo Bool)
       , value ",.." (enumFromThenTo :: EnumFromThenTo Char)
       ]
+
+mk1 :: String -> [Expr] -> Expr -> Expr
+mk1 nm efs ex  =  headOr (err nm efs [ex]) $ efs >$$ ex
+
+mk2 :: String -> [Expr] -> Expr -> Expr -> Expr
+mk2 nm efs ex ey  =  headOr (err nm efs [ex,ey]) $ efs >$$ ex >$$ ey
+
+mk3 :: String -> [Expr] -> Expr -> Expr -> Expr -> Expr
+mk3 nm efs ex ey ez  =  headOr (err nm efs [ex,ey,ez])
+                     $  efs >$$ ex >$$ ey >$$ ez
+
+mk4 :: String -> [Expr] -> Expr -> Expr -> Expr -> Expr -> Expr
+mk4 nm efs ex ey ez ew  =  headOr (err nm efs [ex,ey,ez,ew])
+                        $  efs >$$ ex >$$ ey >$$ ez >$$ ew
+
+mk5 :: String -> [Expr] -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr
+mk5 nm efs ex ey ez ew ev  =  headOr (err nm efs [ex,ey,ez,ew,ev])
+                           $  efs >$$ ex >$$ ey >$$ ez >$$ ew >$$ ev
+
+mk6 :: String -> [Expr] -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr
+mk6 nm efs ex ey ez ew ev eu  =  headOr (err nm efs [ex,ey,ez,ew,ev,eu])
+                              $  efs >$$ ex >$$ ey >$$ ez >$$ ew >$$ ev >$$ eu
+
+err :: String -> [Expr] -> [Expr] -> Expr
+err fn efs exs  =  error
+                $  fn ++ ": unhandled type: "
+                ++ intercalate ", " (map show exs)
+                ++ "\n    accepted types are:\n"
+                ++ unlines (map (("    " ++) . show) efs)
diff --git a/test/fixtures.hs b/test/fixtures.hs
--- a/test/fixtures.hs
+++ b/test/fixtures.hs
@@ -87,6 +87,11 @@
   , show (gg yy) == "g y :: Int"
   , show (ff one) == "f 1 :: Int"
   , show (gg minusTwo) == "g (-2) :: Int"
+  , show (ff xxs) == "f xs :: [Int]"
+  , show (ff emptyString) == "f \"\" :: [Char]"
+  , show (gg (yy -:- yys)) == "g (y:ys) :: [Int]"
+  , show (hh (ae -:- ccs)) == "h ('a':cs) :: [Char]"
+  , show (and' (hh pps)) == "and (h ps) :: Bool"
 
   , show idE == "id :: Int -> Int"
   , show negateE == "negate :: Int -> Int"
@@ -121,6 +126,17 @@
   , show (ooE :$ xx) == "(x `o`) :: Int -> Int"
   , show (ooE :$ xx :$ yy) == "x `o` y :: Int"
 
+  -- a -> a -> ... -> a
+  , show (ff2 xx one) == "f x 1 :: Int"
+  , show (ff2 false pp) == "f False p :: Bool"
+  , show (ff2 xxs zero) == "f xs 0 :: Int"
+  , show (ff3 xx one zero) == "f x 1 0 :: Int"
+  , show (ff3 false pp true) == "f False p True :: Bool"
+  , show (ff3 xxs zero yy) == "f xs 0 y :: Int"
+  , show (ff4 yy xx one zero) == "f y x 1 0 :: Int"
+  , show (ff4 qq false pp true) == "f q False p True :: Bool"
+  , show (ff4 zz xxs zero yy) == "f z xs 0 y :: Int"
+
   -- Char --
 
   , show c_ == "_ :: Char"
@@ -162,12 +178,17 @@
   , show (head' $ zero -:- unit two) == "head [0,2] :: Int"
   , show (tail' $ zero -:- unit two) == "tail [0,2] :: [Int]"
   , show (init' $ zero -:- unit two) == "init [0,2] :: [Int]"
+  , show (drop' two $ zero -:- unit two) == "drop 2 [0,2] :: [Int]"
+  , show (take' three $ zero -:- unit two) == "take 3 [0,2] :: [Int]"
 
   , evl (unit one) == [1 :: Int]
   , evl (head' $ unit one) == (1 :: Int)
   , evl (tail' $ zero -:- unit two) == ([2] :: [Int])
   , evl (init' $ zero -:- unit two) == ([0] :: [Int])
 
+  , evl (drop' one $ zero -:- unit two) == ([2] :: [Int])
+  , evl (take' one $ zero -:- unit two) == ([0] :: [Int])
+
   -- String --
 
   , show emptyString == "\"\" :: [Char]"
@@ -285,4 +306,41 @@
   , evl (negate' twelve `mod'`  seven) == (2 :: Int)
   , evl (negate' twelve `quot'` seven) == (-1 :: Int)
   , evl (negate' twelve `rem'`  seven) == (-5 :: Int)
+
+  -- Maybe
+  , show (just xx) == "Just x :: Maybe Int"
+  , show (just ae) == "Just 'a' :: Maybe Char"
+  , show (just xxs) == "Just xs :: Maybe [Int]"
+  , show (just pps) == "Just ps :: Maybe [Bool]"
+  , show (just false) == "Just False :: Maybe Bool"
+
+  -- Pairs
+  , show (zero -|- one) == "(0,1) :: (Int,Int)"
+  , show (xx -|- yy) == "(x,y) :: (Int,Int)"
+  , show (zz -|- xx) == "(z,x) :: (Int,Int)"
+  , show (zz -|- (xx -+- yy)) == "(z,x + y) :: (Int,Int)"
+  , show (false -|- true) == "(False,True) :: (Bool,Bool)"
+  , show (bee -|- ae) == "('b','a') :: (Char,Char)"
+  , show (ae -|- (bee -:- unit cee)) == "('a',\"bc\") :: (Char,[Char])"
+  , show (xx -|- xxs) == "(x,xs) :: (Int,[Int])"
+  , show (xxs -|- xx) == "(xs,x) :: ([Int],Int)"
+  , show (xx -|- (xx -|- xx)) == "(x,(x,x)) :: (Int,(Int,Int))"
+
+  -- Trios
+  , show (triple zero one two) == "(0,1,2) :: (Int,Int,Int)"
+  , show (triple xx one xxs) == "(x,1,xs) :: (Int,Int,[Int])"
+
+  -- Further tuplings
+  , show (quadruple zero one two three) == "(0,1,2,3) :: (Int,Int,Int,Int)"
+  , show (quintuple zero one two three four) == "(0,1,2,3,4) :: (Int,Int,Int,Int,Int)"
+  , show (sixtuple zero one two three four five) == "(0,1,2,3,4,5) :: (Int,Int,Int,Int,Int,Int)"
+  , show (quadruple pp qq rr pp') == "(p,q,r,p') :: (Bool,Bool,Bool,Bool)"
+  , show (quintuple pp qq rr pp' qq) == "(p,q,r,p',q) :: (Bool,Bool,Bool,Bool,Bool)"
+  , show (sixtuple pp qq rr pp' qq false) == "(p,q,r,p',q,False) :: (Bool,Bool,Bool,Bool,Bool,Bool)"
+
+  -- higher order
+  , show (map' absE (unit minusOne)) == "map abs [-1] :: [Int]"
+  , evl (map' absE (unit minusOne)) == [1 :: Int]
+  , show (foldr' plus zero (unit one)) == "foldr (+) 0 [1] :: Int"
+  , evl (foldr' plus zero (unit one)) == (1 :: Int)
   ]
