express 1.0.14 → 1.0.16
raw patch · 4 files changed
+535/−70 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Express.Fixtures: drop' :: Expr -> Expr -> Expr
+ Data.Express.Fixtures: ff2 :: Expr -> Expr -> Expr
+ Data.Express.Fixtures: ff3 :: Expr -> Expr -> Expr -> Expr
+ Data.Express.Fixtures: ff4 :: Expr -> Expr -> Expr -> Expr -> Expr
+ Data.Express.Fixtures: filter' :: Expr -> Expr -> Expr
+ Data.Express.Fixtures: foldr' :: Expr -> Expr -> Expr -> Expr
+ Data.Express.Fixtures: take' :: Expr -> Expr -> Expr
Files
- changelog.md +10/−0
- express.cabal +2/−2
- src/Data/Express/Fixtures.hs +465/−68
- test/fixtures.hs +58/−0
changelog.md view
@@ -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) ----------------------
express.cabal view
@@ -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
src/Data/Express/Fixtures.hs view
@@ -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)
test/fixtures.hs view
@@ -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) ]