packages feed

code-conjure 0.7.2 → 0.7.4

raw patch · 61 files changed

+666/−733 lines, 61 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Conjure: property :: Testable a => a -> Property
+ Conjure: type Property = [Bool]
+ Conjure.Engine: property :: Testable a => a -> Property
+ Conjure.Engine: type Property = [Bool]
- Conjure: conjureFromSpec :: Conjurable f => String -> (f -> Bool) -> [Ingredient] -> IO ()
+ Conjure: conjureFromSpec :: Conjurable f => String -> (f -> [Property]) -> [Ingredient] -> IO ()
- Conjure.Engine: conjpure0 :: Conjurable f => String -> f -> (f -> Bool) -> [Ingredient] -> Results
+ Conjure.Engine: conjpure0 :: Conjurable f => String -> f -> (f -> [Property]) -> [Ingredient] -> Results
- Conjure.Engine: conjpureFromSpec :: Conjurable f => String -> (f -> Bool) -> [Ingredient] -> Results
+ Conjure.Engine: conjpureFromSpec :: Conjurable f => String -> (f -> [Property]) -> [Ingredient] -> Results
- Conjure.Engine: conjure0 :: Conjurable f => String -> f -> (f -> Bool) -> [Ingredient] -> IO ()
+ Conjure.Engine: conjure0 :: Conjurable f => String -> f -> (f -> [Property]) -> [Ingredient] -> IO ()
- Conjure.Engine: conjureFromSpec :: Conjurable f => String -> (f -> Bool) -> [Ingredient] -> IO ()
+ Conjure.Engine: conjureFromSpec :: Conjurable f => String -> (f -> [Property]) -> [Ingredient] -> IO ()

Files

README.md view
@@ -64,8 +64,8 @@ addition, multiplication, subtraction and their neutral elements:  	ingredients :: [Ingredient]-	ingredients  =  [ con (0::Int)-	                , con (1::Int)+	ingredients  =  [ unfun (0::Int)+	                , unfun (1::Int) 	                , fun "+" ((+) :: Int -> Int -> Int) 	                , fun "*" ((*) :: Int -> Int -> Int) 	                , fun "-" ((-) :: Int -> Int -> Int)@@ -99,7 +99,7 @@ by including [`enumFromTo`] and [`foldr`] in the background.  For more information, see the `eg/factorial.hs` example and-the Haddock documentation for the [`conjure`] and [`conjureWith`] functions.+the Haddock documentation for the [`conjure`] function.   Synthesizing functions over algebraic data types@@ -121,9 +121,9 @@ given list constructors, zero, one and subtraction:  	> conjure "take" (take' :: Int -> [A] -> [A])-	>   [ con (0 :: Int)-	>   , con (1 :: Int)-	>   , con ([] :: [A])+	>   [ unfun (0 :: Int)+	>   , unfun (1 :: Int)+	>   , unfun ([] :: [A]) 	>   , fun ":" ((:) :: A -> [A] -> [A]) 	>   , fun "-" ((-) :: Int -> Int -> Int) 	>   ]@@ -147,164 +147,68 @@ -----------------------------------------------------  Conjure also supports synthesizing from a functional specification-with the functions [`conjureFromSpec`] and [`conjureFromSpecWith`]-as, in some cases,-a partial definition may not be appropriate-for one of two reasons:--1. Conjure may fail to "hit" the appropriate data points;-2. specifying argument-result bindings may not be easy.--Take for example a function `duplicates :: Eq a => [a] -> [a]`-that should return the duplicate elements in a list without repetitions.--We will first try to use a partial definition to arrive at an appropriate result.-Then we'll see how to use [`conjureFromSpec`].--Let's start with the ingredients:--	ingredients :: [Ingredient]-	ingredients  =  [ con ([] :: [Int])-	                , fun "not" not-	                , fun "&&" (&&)-	                , fun ":" ((:) :: Int -> [Int] -> [Int])-	                , fun "elem" (elem :: Int -> [Int] -> Bool)-	                , iif (undefined :: [Int])-	                ]--Now here's a first attempt at a partial definition:--	duplicates' :: [Int] -> [Int]-	duplicates' []  =  []-	duplicates' [1,2,3,4,5]  =  []-	duplicates' [1,2,2,3,4]  =  [2]-	duplicates' [1,2,3,3,3]  =  [3]-	duplicates' [1,2,2,3,3]  =  [2,3]--Here is what [`conjure`] prints:--	> conjure "duplicates" duplicates ingredients-	duplicates :: [Int] -> [Int]-	-- testing 1 combinations of argument values-	-- pruning with 21/26 rules-	-- ...  ...  ...-	duplicates xs  =  xs--The generated function clearly does not follow our specification.-But if we look at the reported number of tests,-we see that only _one_ of the argument-result bindings-of our partial definition was used.-Conjure failed to hit any of the argument values with five elements.-(Since Conjure uses enumeration to test functions these values have to be kept "small").--Here is a second attempt:--	duplicates :: [Int] -> [Int]-	duplicates [0,0]  =  [0]-	duplicates [0,1]  =  []-	duplicates [1,0,1]  =  [1]--Here is what [`conjure`] now prints:--	> conjure "duplicates" duplicates ingredients-	duplicates :: [Int] -> [Int]-	-- testing 3 combinations of argument values-	-- pruning with 21/26 rules-	-- ...  ...  ...-	duplicates []  =  []-	duplicates (x:xs)  =  if elem x xs then [x] else []--The `duplicates` function that Conjure generated is still not correct.-Nevertheless, it does follow our partial definition.  We have to refine it.-Here is a third attempt with more argument-result bindings:--	duplicates :: [Int] -> [Int]-	duplicates [0,0]  =  [0]-	duplicates [0,1]  =  []-	duplicates [1,0,1]  =  [1]-	duplicates [0,1,0,1]  =  [0,1]--Here is what Conjure prints:--	duplicates []  =  []-	duplicates (x:xs)  =  if elem x xs then x:duplicates xs else []--This implementation follows our partial definition, but may return duplicate duplicates,-see:--	duplicates [1,0,1,0,1]  =  [1,0,1]--Here is a fourth and final refinement:--	duplicates :: [Int] -> [Int]-	duplicates [0,0]  =  [0]-	duplicates [0,1]  =  []-	duplicates [1,0,1]  =  [1]-	duplicates [0,1,0,1]  =  [0,1]-	duplicates [1,0,1,0,1]  =  [0,1]-	duplicates [0,1,2,1]  =  [1]--Now Conjure prints a correct implementation:+with [`conjureFromSpec`]. -	> conjure "duplicates" duplicates ingredients-	duplicates :: [Int] -> [Int]-	-- 0.2s, testing 6 combinations of argument values-	-- 0.3s, pruning with 21/26 rules-	-- ...   ...   ...   ...   ...-	-- 2.1s, 1723 candidates of size 17-	-- 2.1s, tested 1705 candidates-	duplicates []  =  []-	duplicates (x:xs)  =  if elem x xs && not (elem x (duplicates xs))-	                      then x:duplicates xs-	                      else duplicates xs+Consider a function `duplicates` that given a list of values+should return all values that are repeated.+The resulting list should itself not contain repetitions. -In this case,-specifying the function with specific argument-result bindings-is perhaps not the best approach.-It took us four refinements of the partial definition to get a result.-Specifying test properties perhaps better describes what we want.-Again, we would like `duplicates` to return all duplicate elements-without repetitions.-This can be encoded in a function using [`holds`] from [LeanCheck]:+Even an experienced programmer+may take a few minutes to come up with a correct definition for `duplicates`+even when told that a conditional definition+is possible using only+`[]`,+`:`,+`not`,+`&&` and+`elem`.+(We invite the reader to try.) -	import Test.LeanCheck (holds)+We can encode a specification of duplicates with test properties like so: -	duplicatesSpec :: ([Int] -> [Int]) -> Bool+	duplicatesSpec :: ([Int] -> [Int]) -> [Property] 	duplicatesSpec duplicates  =  and-	  [ holds 360 $ \x xs -> (count (x ==) xs > 1) == elem x (duplicates xs)-	  , holds 360 $ \x xs -> count (x ==) (duplicates xs) <= 1+	  [ property $ \x xs -> (count (x ==) xs > 1) == elem x (duplicates xs)+	  , property $ \x xs -> count (x ==) (duplicates xs) <= 1 	  ]  where  count p  =  length . filter p -This function takes as argument a candidate implementation of `duplicates`-and returns whether it is valid.-The first property states that all duplicates must be listed.-The second property states that duplicates themselves must not repeat.--Now, we can use the function [`conjureFromSpecWith`] to generate the same duplicates function-passing our `duplicatesSpec` as argument:--	> conjureFromSpecWith args{maxSize=18} "duplicates" duplicatesSpec ingredients-	duplicates :: [Int] -> [Int]-	duplicates []  =  []-	duplicates (x:xs)  =  if elem x xs && not (elem x (duplicates xs)) then x:duplicates xs else duplicates xs-	(in 1.5s)--For more information see the `eg/dupos.hs` example and-the Haddock documentation for the [`conjureFromSpec`] and [`conjureFromSpecWith`] functions.+Conjure finds a solution in 1 second+with the following call: -The functions [`conjureFromSpec`] and [`conjureFromSpecWith`] also accept specifications-that bind specific arguments to results.-Just use `==` and `&&` accordingly:+	conjureFromSpec "duplicates" duplicatesSpec+	  [ unfun ([] :: [Int])+	  , fun "not" not+	  , fun "&&" (&&)+	  , fun ":" ((:) :: Int -> [Int] -> [Int])+	  , fun "elem" (elem :: Int -> [Int] -> Bool)+	  , guard  -- allows guards+	  ] -	duplicatesSpec :: ([Int] -> [Int]) -> Bool-	duplicatesSpec duplicates  =  duplicates [0,0] == [0]-	                           && duplicates [0,1]  ==  []-	                           && duplicates [1,0,1]  ==  [1]-	                           && duplicates [0,1,0,1]  ==  [0,1]-	                           && duplicates [1,0,1,0,1]  ==  [0,1]-	                           && duplicates [0,1,2,1]  ==  [1]+This is the definition produced by Conjure: -With this, there is no way for Conjure to miss argument-result bindings.+	duplicates []  =  []+	-- 0.2s, pruning with 21/26 rules+	-- 0.2s, 2 candidates of size 1+	-- 0.3s, 1 candidates of size 2+	-- 0.3s, 0 candidates of size 3+	-- 0.3s, 2 candidates of size 4+	-- 0.3s, 1 candidates of size 5+	-- 0.3s, 2 candidates of size 6+	-- 0.3s, 3 candidates of size 7+	-- 0.3s, 8 candidates of size 8+	-- 0.3s, 13 candidates of size 9+	-- 0.3s, 18 candidates of size 10+	-- 0.3s, 21 candidates of size 11+	-- 0.3s, 28 candidates of size 12+	-- 0.3s, 39 candidates of size 13+	-- 0.4s, 54 candidates of size 14+	-- 0.5s, 67 candidates of size 15+	-- 0.7s, 80 candidates of size 16+	-- 1.0s, 99 candidates of size 17+	-- 1.0s, tested 340 candidates+	duplicates (x:xs)+	  | elem x xs && not (elem x (duplicates xs))  =  x:duplicates xs+	  | otherwise  =  duplicates xs   Related work@@ -381,9 +285,7 @@  [Conjure's Haddock documentation]: https://hackage.haskell.org/package/code-conjure/docs/Conjure.html [`conjure`]:             https://hackage.haskell.org/package/code-conjure/docs/Conjure.html#v:conjure-[`conjureWith`]:         https://hackage.haskell.org/package/code-conjure/docs/Conjure.html#v:conjureWith [`conjureFromSpec`]:     https://hackage.haskell.org/package/code-conjure/docs/Conjure.html#v:conjureFromSpec-[`conjureFromSpecWith`]: https://hackage.haskell.org/package/code-conjure/docs/Conjure.html#v:conjureFromSpecWith  [`foldr`]:               https://hackage.haskell.org/package/base/docs/Prelude.html#v:foldr [`enumFromTo`]:          https://hackage.haskell.org/package/base/docs/Prelude.html#v:enumFromTo
bench/candidates.hs view
@@ -40,43 +40,43 @@ main :: IO () main  =  do   printCandidates 9 6 "foo" (undefined :: Int -> Int)-    [ con (0 :: Int)-    , con (1 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)     ]    printCandidates 9 5 "?" (undefined :: Int -> Int -> Int)-    [ con (0 :: Int)+    [ unfun (0 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "dec" (subtract 1 :: Int -> Int)     ]    printCandidates 9 6 "goo" (undefined :: [Int] -> [Int])-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     ]    printCandidates 9 6 "??" (undefined :: [Int] -> [Int] -> [Int])-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     ]    printCandidates 9 6 "ton" (undefined :: Bool -> Bool)-    [ con False-    , con True+    [ unfun False+    , unfun True     , fun "&&" (&&)     , fun "||" (||)     , fun "not" not     ]    printCandidates 9 6 "&|" (undefined :: Bool -> Bool -> Bool)-    [ con False-    , con True+    [ unfun False+    , unfun True     , fun "&&" (&&)     , fun "||" (||)     , fun "not" not@@ -88,6 +88,6 @@   -- nevertheless useful for observing candidate filtering   -- through other means   printCandidates 9 6 "gcd" (undefined :: Int -> Int -> Int)-    [ con (0::Int)+    [ unfun (0::Int)     , fun "`mod`" (mod :: Int -> Int -> Int)     ]
bench/carry-on.hs view
@@ -15,8 +15,8 @@ main  =  do   -- carry on Conjuring larger implementations   conjure "factorial n" factorial-    [ con (0::Int)-    , con (1::Int)+    [ unfun (0::Int)+    , unfun (1::Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)
bench/erroneous.hs view
@@ -58,44 +58,44 @@   let n = 6    printErroneousCandidates (n+1) "foo" (undefined :: Int -> Int)-    [ con (0 :: Int)-    , con (1 :: Int)-    , con (2 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)+    , unfun (2 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)     ]    printErroneousCandidates n "?" (undefined :: Int -> Int -> Int)-    [ con (0 :: Int)+    [ unfun (0 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "dec" (subtract 1 :: Int -> Int)     ]    printErroneousCandidates (n+1) "goo" (undefined :: [Int] -> [Int])-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     ]    printErroneousCandidates n "??" (undefined :: [Int] -> [Int] -> [Int])-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     ]    printErroneousCandidates n "ton" (undefined :: Bool -> Bool)-    [ con False-    , con True+    [ unfun False+    , unfun True     , fun "&&" (&&)     , fun "||" (||)     , fun "not" not     ]    printErroneousCandidates n "&|" (undefined :: Bool -> Bool -> Bool)-    [ con False-    , con True+    [ unfun False+    , unfun True     , fun "&&" (&&)     , fun "||" (||)     , fun "not" not
bench/gps.hs view
@@ -44,10 +44,10 @@  gps1c30p :: IO () gps1c30p  =  conjure "gps1" gps1p-  [ con (0 :: Float)-  , con (1 :: Float)-  , con (1/2 :: Float)-  , con (-1 :: Float)+  [ unfun (0 :: Float)+  , unfun (1 :: Float)+  , unfun (1/2 :: Float)+  , unfun (-1 :: Float)   , fun "+" ((+) :: Float -> Float -> Float)   , fun "*" ((*) :: Float -> Float -> Float)   , fun "-" ((-) :: Float -> Float -> Float)@@ -56,9 +56,9 @@   , fun "id" (id :: Float -> Float)   , fun "fromIntegral" (fromIntegral :: Int -> Float) -  , con (0 :: Int)-  , con (1 :: Int)-  , con (-1 :: Int)+  , unfun (0 :: Int)+  , unfun (1 :: Int)+  , unfun (-1 :: Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "*" ((*) :: Int -> Int -> Int)   , fun "-" ((-) :: Int -> Int -> Int)@@ -71,8 +71,8 @@   , fun "round" (round :: Float -> Int)   , fun "truncate" (truncate :: Float -> Int) -  , con False-  , con True+  , unfun False+  , unfun True   , fun "&&" (&&)   , fun "||" (||)   , fun "not" not@@ -95,10 +95,10 @@  gps2c :: IO () gps2c  =  conjure "gps2" gps2p-  [ con "small"-  , con "large"-  , con (1000 :: Int)-  , con (2000 :: Int)+  [ unfun "small"+  , unfun "large"+  , unfun (1000 :: Int)+  , unfun (2000 :: Int)   , fun "Just" (Just :: String -> Maybe String)   , fun "Nothing" (Nothing :: Maybe String)   , fun "<=" ((<=) :: Int -> Int -> Bool)@@ -124,7 +124,7 @@ gps3c :: IO () gps3c  =  do   conjure "gps3" gps3p-    [ con (1 :: Int)+    [ unfun (1 :: Int)     , fun "enumFromThenTo" ((\x y z -> take 720 $ enumFromThenTo x y z) :: Int -> Int -> Int -> [Int])     , fun "+" ((+) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)@@ -132,7 +132,7 @@    -- not possible, no recursive descent   conjure "gps3" gps3p-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "+" ((+) :: Int -> Int -> Int)     , fun "<" ((<) :: Int -> Int -> Bool)@@ -180,9 +180,9 @@  gps5c :: IO () gps5c  =  conjure "gps5" gps5p -- can't find-  [ con ""+  [ unfun ""   , fun ":" ((:) :: Char -> String -> String)-  , con '!'+  , unfun '!'   , fun "==" ((==) :: Char -> Char -> Bool)   , fun "isLetter" (isLetter :: Char -> Bool)   , iif (undefined :: String -> String)@@ -218,9 +218,9 @@ -- But a size of 15 or 17 is simplyl out of our reach. gps6c :: IO () gps6c  =  conjure "gps6" gps6p-  [ con (1 :: Int)-  , con (2 :: Int)-  , con (3 :: Int)+  [ unfun (1 :: Int)+  , unfun (2 :: Int)+  , unfun (3 :: Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "*" ((*) :: Int -> Int -> Int)   , fun "`div`" (div :: Int -> Int -> Int)@@ -301,7 +301,7 @@  gps9c :: IO () gps9c  =  conjure "gps9" gps9p-  [ con (1 :: Int)+  [ unfun (1 :: Int)   , fun "map" (map :: (Int -> Int) -> [Int] -> [Int])   , fun "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])   , fun ".." (enumFromTo :: Int -> Int -> [Int])@@ -353,8 +353,8 @@ gps10c :: IO () gps10c  =  do   conjure "wallisNext" wallisNextP-    [ con (1 :: Integer)-    , con (2 :: Integer)+    [ unfun (1 :: Integer)+    , unfun (2 :: Integer)     , fun "+" ((+) :: Integer -> Integer -> Integer)     , fun "*" ((*) :: Integer -> Integer -> Integer)     , fun "%" ((%) :: Integer -> Integer -> Rational)@@ -366,18 +366,18 @@    -- simplified background   conjure "wallisNext" wallisNextP-    [ con (0 :: Integer)-    , con (1 :: Integer)+    [ unfun (0 :: Integer)+    , unfun (1 :: Integer)     , fun "+" ((+) :: Integer -> Integer -> Integer)     , fun "*" ((*) :: Integer -> Integer -> Integer)     , fun "%" ((%) :: Integer -> Integer -> Rational)     ]    conjure "gps10" gps10p-    [ con (2 :: Integer)-    , con (3 :: Integer)+    [ unfun (2 :: Integer)+    , unfun (3 :: Integer)     , fun "%" ((%) :: Integer -> Integer -> Rational)---  , con (2/3 :: Rational)+--  , unfun (2/3 :: Rational)     , fun "product"    (product :: [Rational] -> Rational)     , fun "take"       (take :: Int -> [Rational] -> [Rational])     , fun "iterate"    ((\f -> take 720 . iterate f) :: (Rational -> Rational) -> Rational -> [Rational])@@ -409,7 +409,7 @@     ]    conjure "gps11" gps11p-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     , fun "length"  (length :: String -> Int)@@ -438,8 +438,8 @@     , fun "fromJust"  (fromJust :: Maybe Int -> Int)     , fun "-"         ((-) :: Int -> Int -> Int)     , fun "=="        ((==) :: Int -> Int -> Bool)-    , con (0 :: Int)-    , con (1 :: Int)+    , unfun (0 :: Int)+    , unfun (1 :: Int)     , maxSize 11     ] @@ -496,9 +496,9 @@ gps14c :: IO () gps14c  =  do   conjure "odd" odd'-    [ con (0 :: Int)-    , con (1 :: Int)-    , con (2 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)+    , unfun (2 :: Int)     , fun "`mod`" (mod :: Int -> Int -> Int)     , fun "/=" ((/=) :: Int -> Int -> Bool)     ]@@ -513,9 +513,9 @@   -- gps14 []  =  0   -- gps14 (x:xs)  =  x `mod` 2 + gps14 xs   conjure "gps14" gps14p-    [ con (0 :: Int)-    , con (1 :: Int)-    , con (2 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)+    , unfun (2 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "`mod`" (mod :: Int -> Int -> Int)     , fun "==" ((==) :: Int -> Int -> Bool)@@ -577,8 +577,8 @@  gps17c :: IO () gps17c  =  conjure "gps17" gps17p-  [ con (0 :: Int)-  , con (1 :: Int)+  [ unfun (0 :: Int)+  , unfun (1 :: Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "*" ((*) :: Int -> Int -> Int)   , fun "-" ((-) :: Int -> Int -> Int)@@ -602,7 +602,7 @@ gps18c :: IO () gps18c  =  do   conjure "gps18" gps18p-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun "+" ((+) :: Int -> Int -> Int)     , fun ":" ((:) :: Int -> [Int] -> [Int])     ]@@ -641,9 +641,11 @@   -- GPS Benchmark #20 -- Pig Latin ---gps20s :: (String -> String) -> Bool-gps20s pig  =  pig "hello world" == "ellohay orldway"-            && pig "a string"    == "aay tringsay"+gps20s :: (String -> String) -> [Property]+gps20s pig  =+  [ property $ pig "hello world" == "ellohay orldway"+  , property $ pig "a string"    == "aay tringsay"+  ]  gps20g :: String -> String gps20g  =  pig@@ -656,11 +658,13 @@                 then (c:cs) ++ "ay"                 else cs ++ (c:"ay") -pig1Spec :: (String -> String) -> Bool-pig1Spec pig1  =  pig1 "hello" == "ellohay"-               && pig1 "world"  == "orldway"-               && pig1 "string" == "tringsay"-               && pig1 "east"   == "eastay"+pig1Spec :: (String -> String) -> [Property]+pig1Spec pig1  =+  [ property $ pig1 "hello" == "ellohay"+  , property $ pig1 "world"  == "orldway"+  , property $ pig1 "string" == "tringsay"+  , property $ pig1 "east"   == "eastay"+  ]  isVowel :: Char -> Bool isVowel 'a'  =  True@@ -688,18 +692,18 @@ gps20c :: IO () gps20c  =  do   conjure "isVowel" isVowel'-    [ con 'a'-    , con 'e'-    , con 'i'-    , con 'o'-    , con 'u'-    , con 'y'-    , con True-    , con False+    [ unfun 'a'+    , unfun 'e'+    , unfun 'i'+    , unfun 'o'+    , unfun 'u'+    , unfun 'y'+    , unfun True+    , unfun False     ]    conjureFromSpec "pig1" pig1Spec-    [ con "ay"+    [ unfun "ay"     , iif (undefined :: String)     , fun "isVowel" isVowel     , fun "++" ((++) :: String -> String -> String)@@ -730,8 +734,8 @@  gps21c :: IO () gps21c  =  conjure "gps21" gps21p-  [ con ([] :: [Int])-  , con (0 :: Int)+  [ unfun ([] :: [Int])+  , unfun (0 :: Int)   , fun ":" ((:) :: Int -> [Int] -> [Int])   , fun "<" ((<) :: Int -> Int -> Bool)   , iif (undefined :: Int)@@ -739,11 +743,13 @@   -- GPS Benchmark #22 -- Scrabble Score ---gps22s :: (String -> Int) -> Bool-gps22s scrabble  =  scrabble "a" == 1-                 && scrabble "hello" == 8-                 && scrabble "world" == 9-                 && scrabble "scrabble" == 14+gps22s :: (String -> Int) -> [Property]+gps22s scrabble  =+  [ property $ scrabble "a" == 1+  , property $ scrabble "hello" == 8+  , property $ scrabble "world" == 9+  , property $ scrabble "scrabble" == 14+  ]  gps22g :: String -> Int gps22g  =  scrabble@@ -773,7 +779,7 @@ gps22c :: IO () gps22c  =  do   conjureFromSpec "gps22" gps22s-    [ con (0 :: Int)+    [ unfun (0 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "map" (map :: (Int -> Int) -> [Int] -> [Int])     , fun "scrabble1" scrabble1@@ -802,8 +808,8 @@  gps24c :: IO () gps24c  =  conjure "gps24" gps24p-  [ con ' '-  , con (64 :: Int)+  [ unfun ' '+  , unfun (64 :: Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "`mod`" (mod :: Int -> Int -> Int)   , fun "sum" (sum :: [Int] -> Int)@@ -829,9 +835,9 @@ -- out of reach performance-wise gps25c :: IO () gps25c  =  conjure "gps25" gps25p $ take 0-  [ con (0 :: Int)-  , con (10 :: Int)-  , con ([] :: [Int])+  [ unfun (0 :: Int)+  , unfun (10 :: Int)+  , unfun ([] :: [Int])   , fun ":" ((:) :: Int -> [Int] -> [Int])   , iif (undefined :: [Int])   , fun "abs" (abs :: Int -> Int)@@ -861,11 +867,11 @@ -- out of reach performance-wise gps26c :: IO () gps26c  =  conjure "gps26" gps26p-  [ con 'A'-  , con 'B'-  , con 'C'-  , con 'D'-  , con 'F'+  [ unfun 'A'+  , unfun 'B'+  , unfun 'C'+  , unfun 'D'+  , unfun 'F'   , iif (undefined :: Char)   , fun ">=" ((>=) :: Int -> Int -> Bool)   , maxSize 2@@ -914,13 +920,15 @@   -- GPS Benchmark #29 -- Syllables ---gps29s :: (String -> Int) -> Bool-gps29s sys  =  sys "pub" == 1-            && sys "hello" == 2-            && sys "world" == 1-            && sys "string" == 1-            && sys "haskell" == 2-            && sys "photography" == 4+gps29s :: (String -> Int) -> [Property]+gps29s sys  =+  [ property $ sys "pub" == 1+  , property $ sys "hello" == 2+  , property $ sys "world" == 1+  , property $ sys "string" == 1+  , property $ sys "haskell" == 2+  , property $ sys "photography" == 4+  ]  gps29g :: String -> Int gps29g ""  =  0@@ -930,8 +938,8 @@  gps29c :: IO () gps29c  =  conjureFromSpec "gps29" gps29s-  [ con (0 :: Int)-  , con (1 :: Int)+  [ unfun (0 :: Int)+  , unfun (1 :: Int)   , fun "+" ((+) :: Int->Int->Int)   , iif (undefined :: Int)   , fun "isVowel" isVowel
bench/gps2.hs view
@@ -42,7 +42,7 @@ gps1c :: IO () gps1c  =  do   conjure "gps1" gps1p-    [ con (0 :: Int)+    [ unfun (0 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun ">" ((>) :: Int -> Int -> Bool)     , fun "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)@@ -54,7 +54,7 @@     ]    conjure "gps1" gps1p-    [ con (0 :: Int)+    [ unfun (0 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun ">" ((>) :: Int -> Int -> Bool)     , fun "sum" (sum :: [Int] -> Int)@@ -66,8 +66,8 @@     ]    conjure "gps1" gps1p2-    [ con (0 :: Int)-    , con (1 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "<" ((<) :: Int -> Int -> Bool)     , iif (undefined :: Int)@@ -93,8 +93,8 @@ gps2c :: IO () gps2c  =  do   conjure "gps2" gps2p-    [ con (0 :: Int)-    , con (1 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "*" ((*) :: Double -> Double -> Double)     , fun "/" ((/) :: Double -> Double -> Double)     , fun "+" ((+) :: Double -> Double -> Double)@@ -119,10 +119,12 @@ -- considering we're getting input as kebab-case. -- Nevertheless, this one is out of reach performance-wise (and OOM-wise) -gps4s :: (String -> String) -> Bool-gps4s g  =  g "the-stealth-warrior" == "theStealthWarrior"-         && g "camel-case" == "camelCase"-         && g "Kebab-Case" == "KebabCase"+gps4s :: (String -> String) -> [Property]+gps4s g  =+  [ property $ g "the-stealth-warrior" == "theStealthWarrior"+  , property $ g "camel-case" == "camelCase"+  , property $ g "Kebab-Case" == "KebabCase"+  ]  gps4g :: String -> String gps4g ""  =  ""@@ -137,8 +139,8 @@ gps4c :: IO () gps4c  =  do   conjureFromSpec "gps4" gps4s-    [ con '-'-    , con ("" :: String)+    [ unfun '-'+    , unfun ("" :: String)     , fun ":" ((:) :: Char -> String -> String)     , fun "==" ((==) :: Char -> Char -> Bool)     , fun "head" (head :: String -> Char)@@ -170,13 +172,15 @@ gps5p  20  =  [0, 2, 0, 0] gps5p   3  =  [0, 0, 0, 3] -gps5s :: ([Int] -> Int -> [Int]) -> Bool-gps5s t  =  t [25, 10, 5, 1] 100 == [4, 0, 0, 0]-         && t [25, 10, 5, 1]  50 == [2, 0, 0, 0]-         && t [25, 10, 5, 1]  25 == [1, 0, 0, 0]-         && t [25, 10, 5, 1]  30 == [1, 0, 1, 0]-         && t [25, 10, 5, 1]  20 == [0, 2, 0, 0]-         && t [25, 10, 5, 1]   3 == [0, 0, 0, 3]+gps5s :: ([Int] -> Int -> [Int]) -> [Property]+gps5s t  =+  [ property $ t [25, 10, 5, 1] 100 == [4, 0, 0, 0]+  , property $ t [25, 10, 5, 1]  50 == [2, 0, 0, 0]+  , property $ t [25, 10, 5, 1]  25 == [1, 0, 0, 0]+  , property $ t [25, 10, 5, 1]  30 == [1, 0, 1, 0]+  , property $ t [25, 10, 5, 1]  20 == [0, 2, 0, 0]+  , property $ t [25, 10, 5, 1]   3 == [0, 0, 0, 3]+  ]  coins :: [Int] coins  =  [25, 10, 5, 1]@@ -196,23 +200,23 @@     ]    conjureFromSpec "tell" gps5s-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "`div`" (div :: Int -> Int -> Int)     , fun "`mod`" (mod :: Int -> Int -> Int)     ]    conjure "gps5" gps5p-    [ con coins+    [ unfun coins     , fun "tell" tell     ]    conjure "gps5" gps5p-    [ con (1 :: Int)-    , con (5 :: Int)-    , con (10 :: Int)-    , con (25 :: Int)-    , con ([] :: [Int])+    [ unfun (1 :: Int)+    , unfun (5 :: Int)+    , unfun (10 :: Int)+    , unfun (25 :: Int)+    , unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "tell" tell     , target 50400@@ -255,8 +259,8 @@ gps7c :: IO () gps7c  =  do   conjure "gps7" gps7p $ take 0-    [ con (0 :: Integer)-    , con (1 :: Integer)+    [ unfun (0 :: Integer)+    , unfun (1 :: Integer)     , fun "%" ((%) :: Integer -> Integer -> Rational)     , fun "+" ((+) :: Integer -> Integer -> Integer)     , fun "-" ((-) :: Integer -> Integer -> Integer)@@ -326,10 +330,10 @@ -- unreachable due to lambda gps10c :: IO () gps10c  =  conjure "gps10" gps10p-  [ con (0 :: Int)-  , con (1 :: Int)-  , con (2 :: Int)-  , con (3 :: Int)+  [ unfun (0 :: Int)+  , unfun (1 :: Int)+  , unfun (2 :: Int)+  , unfun (3 :: Int)   , fun "`div`" (div :: Int -> Int -> Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "-" ((-) :: Int -> Int -> Int)@@ -355,7 +359,7 @@  gps11c :: IO () gps11c  =  conjure "gcd a b" gps11p-  [ con (0::Int)+  [ unfun (0::Int)   , fun "`mod`" (mod :: Int -> Int -> Int)   ]   -- generated function:@@ -397,7 +401,7 @@  gps13c :: IO () gps13c  =  conjure "gps13_leaders" gps13p-  [ con ([] :: [Int])+  [ unfun ([] :: [Int])   , fun ":" ((:) :: Int -> [Int] -> [Int])   , fun ">" ((>) :: Int -> Int -> Bool)   , fun "all" (all :: (Int -> Bool) -> [Int] -> Bool)@@ -467,8 +471,8 @@  gps16c :: IO () gps16c  =  conjure "gps16_middle" gps16p-  [ con ""-  , con (1 :: Int)+  [ unfun ""+  , unfun (1 :: Int)   , fun "<=" ((<=) :: Int -> Int -> Bool)   , fun ":" ((:) :: Char -> String -> String)   , fun "length" (length :: String -> Int)@@ -501,7 +505,7 @@ -- BENCHMARK: increase maxSize from 5 to 18 gps17c :: IO () gps17c  =  conjure "gps17_pds" gps17p-  [ con (0 :: Int)+  [ unfun (0 :: Int)   , iif (undefined :: Int)   , fun "not" not   , fun "null" (null :: [Int] -> Bool)@@ -525,8 +529,8 @@ -- this was OOM'd gps18c :: IO () gps18c  =  conjure "gps18_price" gps18p-  [ con (0 :: Double)-  , con (1 :: Double)+  [ unfun (0 :: Double)+  , unfun (1 :: Double)   , fun "+" ((+) :: Double -> Double -> Double)   , fun "*" ((*) :: Double -> Double -> Double)   , fun "-" ((-) :: Double -> Double -> Double)@@ -553,8 +557,8 @@  gps19c :: IO () gps19c  =  conjure "gps19_snowday" gps19p-  [ con (0 :: Int)-  , con (1 :: Int)+  [ unfun (0 :: Int)+  , unfun (1 :: Int)   , fun "max" (max :: Double -> Double -> Double)   , fun "+" ((+) :: Double -> Double -> Double)   , fun "-" ((-) :: Double -> Double -> Double)@@ -571,20 +575,24 @@   ]  -gps21s :: (String -> String) -> Bool-gps21s s  =  s "word" == "word"-          && s "words" == "sdrow"-          && s "word words" == "word sdrow"-          && s "words word" == "sdrow word"+gps21s :: (String -> String) -> [Property]+gps21s s  =+  [ property $ s "word" == "word"+  , property $ s "words" == "sdrow"+  , property $ s "word words" == "word sdrow"+  , property $ s "words word" == "sdrow word"+  ] -spinSpec :: (String -> String) -> Bool-spinSpec spin  =  spin "abc" == "abc"-               && spin "abcd" == "abcd"-               && spin "word" == "word"-               && spin "abcde" == "edcba"-               && spin "words" == "sdrow"-               && spin "hello" == "olleh"-               && spin "world" == "dlrow"+spinSpec :: (String -> String) -> [Property]+spinSpec spin  =+  [ property $ spin "abc" == "abc"+  , property $ spin "abcd" == "abcd"+  , property $ spin "word" == "word"+  , property $ spin "abcde" == "edcba"+  , property $ spin "words" == "sdrow"+  , property $ spin "hello" == "olleh"+  , property $ spin "world" == "dlrow"+  ]  spin :: String -> String spin w  =  if length w >= 5@@ -601,7 +609,7 @@     , fun "reverse" (reverse :: String -> String)     , iif (undefined :: String)     , fun ">="      ((>=) :: Int -> Int -> Bool)-    , con (5 :: Int)+    , unfun (5 :: Int)     ]    conjureFromSpec "gps21_spinwords" gps21s@@ -613,7 +621,7 @@     , fun "reverse" (reverse :: String -> String)     , iif (undefined :: String)     , fun ">="      ((>=) :: Int -> Int -> Bool)-    , con (5 :: Int)+    , unfun (5 :: Int)     ]  @@ -635,12 +643,12 @@ gps22c  =  do   -- cannot conjure at size 13, maybe beyond?   conjure "digits" digits'-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "`div`" (div :: Int -> Int -> Int)     , fun "`mod`" (mod :: Int -> Int -> Int)     , fun "div10" ((`div` 10) :: Int -> Int)-    , con (10 :: Int)+    , unfun (10 :: Int)     , target 10080     ] @@ -649,11 +657,13 @@     ]  -gps23s :: (String -> String -> String -> String) -> Bool-gps23s s  =  s "abcd" "abcd" "abcd" == "abcd"-          && s "abcd" "dcba" "abcd" == "dcba"-          && s "abcd" "1234" "abcd" == "1234"-          && s "abcd" "1234" "bacd" == "2134"+gps23s :: (String -> String -> String -> String) -> [Property]+gps23s s  =+  [ property $ s "abcd" "abcd" "abcd" == "abcd"+  , property $ s "abcd" "dcba" "abcd" == "dcba"+  , property $ s "abcd" "1234" "abcd" == "1234"+  , property $ s "abcd" "1234" "bacd" == "2134"+  ]  gps23g :: String -> String -> String -> String -- gps23g f t s  =  map (\c -> fromJust $ c `lookup` zipWith (,) f t) s@@ -687,23 +697,25 @@                      then TooMany                      else Tweet (length s) -gps24s_twitter :: (String -> Twitter) -> Bool-gps24s_twitter twitter  =  twitter "" == Empty-                        && twitter "abcd" == Tweet 4-                        && twitter "0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij" == Tweet 140-                        && twitter "0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghijX" == TooMany+gps24s_twitter :: (String -> Twitter) -> [Property]+gps24s_twitter twitter  =+  [ property $ twitter "" == Empty+  , property $ twitter "abcd" == Tweet 4+  , property $ twitter "0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij" == Tweet 140+  , property $ twitter "0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghij0123456789abcdefghijX" == TooMany+  ]  gps24c :: IO () gps24c  =  do   conjureFromSpec "gps24" gps24s_twitter-    [ con Empty-    , con TooMany+    [ unfun Empty+    , unfun TooMany     , fun "Tweet" Tweet     , iif (undefined :: Twitter)-    , con ""+    , unfun ""     , fun ":" ((:) :: Char -> String -> String)     , fun "length" (length :: String -> Int)-    , con (140 :: Int)+    , unfun (140 :: Int)     , fun ">" ((>) :: Int -> Int -> Bool)     ] @@ -723,8 +735,8 @@ -- out of reach performance-wise gps25c :: IO () gps25c  =  conjure "gps25" gps25p-  [ con (0 :: Double)-  , con (2 :: Double)+  [ unfun (0 :: Double)+  , unfun (2 :: Double)   , fun "+" ((+) :: Double -> Double -> Double)   , fun "-" ((-) :: Double -> Double -> Double)   , fun "**" ((**) :: Double -> Double -> Double)
bench/ill-hit.hs view
@@ -14,13 +14,15 @@ sum' [3,4,5]  =  12 sum' [1,2,3,4]  =  10 -sumSpec :: ([Int] -> Int) -> Bool-sumSpec sum  =  sum [] == 0-             && sum [1] == 1-             && sum [1,2] == 3-             && sum [1,2,3] == 6-             && sum [3,4,5] == 12-             && sum [1,2,3,4] == 10+sumSpec :: ([Int] -> Int) -> [Property]+sumSpec sum  =+  [ property $ sum [] == 0+  , property $ sum [1] == 1+  , property $ sum [1,2] == 3+  , property $ sum [1,2,3] == 6+  , property $ sum [3,4,5] == 12+  , property $ sum [1,2,3,4] == 10+  ]  main :: IO () main  =  do@@ -36,8 +38,8 @@  ingredients :: [Ingredient] ingredients =-  [ con (0 :: Int)-  , con (1 :: Int)+  [ unfun (0 :: Int)+  , unfun (1 :: Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "*" ((*) :: Int -> Int -> Int)   , fun "null" (null :: [Int] -> Bool)
bench/p12.hs view
@@ -47,15 +47,15 @@  ingredients :: [Ingredient] ingredients  =-  [ con (0::Int)-  , con (1::Int)+  [ unfun (0::Int)+  , unfun (1::Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "*" ((*) :: Int -> Int -> Int)   , fun "dec" (subtract 1 :: Int -> Int)    , fun "==" ((==) :: Int -> Int -> Bool) -  , con ([] :: [Int])+  , unfun ([] :: [Int])   , fun ":" ((:) :: Int -> [Int] -> [Int])   , fun "head" (head :: [Int] -> Int)   , fun "tail" (tail :: [Int] -> [Int])
bench/p30.hs view
@@ -47,14 +47,14 @@  ingredients :: [Ingredient] ingredients  =-  [ con False-  , con True+  [ unfun False+  , unfun True   , fun "&&" (&&)   , fun "||" (||)   , fun "not" not -  , con (0::Int)-  , con (1::Int)+  , unfun (0::Int)+  , unfun (1::Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "*" ((*) :: Int -> Int -> Int)   , fun "dec" (subtract 1 :: Int -> Int)@@ -66,7 +66,7 @@    , fun "const" (const :: Int -> Int -> Int) -  , con ([] :: [Int])+  , unfun ([] :: [Int])   , fun ":" ((:) :: Int -> [Int] -> [Int])   , fun "head" (head :: [Int] -> Int)   , fun "tail" (tail :: [Int] -> [Int])
bench/redundants.hs view
@@ -66,43 +66,43 @@   -- We can also customize the n per-function below:    printRedundantCandidates (n+1) "foo" (undefined :: Int -> Int)-    [ con (0 :: Int)-    , con (1 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)     ]    printRedundantCandidates n "?" (undefined :: Int -> Int -> Int)-    [ con (0 :: Int)+    [ unfun (0 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "dec" (subtract 1 :: Int -> Int)     ]    printRedundantCandidates (n+1) "goo" (undefined :: [Int] -> [Int])-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     ]    printRedundantCandidates n "??" (undefined :: [Int] -> [Int] -> [Int])-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     ]    printRedundantCandidates (n+1) "ton" (undefined :: Bool -> Bool)-    [ con False-    , con True+    [ unfun False+    , unfun True     , fun "&&" (&&)     , fun "||" (||)     , fun "not" not     ]    printRedundantCandidates n "&|" (undefined :: Bool -> Bool -> Bool)-    [ con False-    , con True+    [ unfun False+    , unfun True     , fun "&&" (&&)     , fun "||" (||)     , fun "not" not@@ -115,7 +115,7 @@   -- through other means   {-   printRedundantCandidates n "gcd" (undefined :: Int -> Int -> Int)-    [ con (0::Int)+    [ unfun (0::Int)     , fun "`mod`" (mod :: Int -> Int -> Int)     ]   -}
bench/runtime/zero/eg/dupos.runtime view
@@ -1,1 +1,1 @@-3.6+3.7
bench/runtime/zero/eg/ints.runtime view
@@ -1,1 +1,1 @@-1.0+1.9
bench/runtime/zero/eg/list.runtime view
@@ -1,1 +1,1 @@-1.1+1.6
bench/runtime/zero/eg/setelem.runtime view
@@ -1,1 +1,1 @@-2.1+1.9
bench/self.hs view
@@ -13,8 +13,8 @@  ingredients :: [Ingredient] ingredients =-  [ con (0::Int)-  , con (1::Int)+  [ unfun (0::Int)+  , unfun (1::Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "*" ((*) :: Int -> Int -> Int)   , maxSize 3
bench/strategies.hs view
@@ -61,8 +61,8 @@  ingredients :: [Ingredient] ingredients = -    [ con (0::Int)-    , con (1::Int)+    [ unfun (0::Int)+    , unfun (1::Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)
bench/terpret.hs view
@@ -33,12 +33,12 @@ -- the same ingredients are used for TerpreT #1, #2 and #3 ingredients123 :: [Ingredient] ingredients123  =-  [ con False-  , con True+  [ unfun False+  , unfun True   , fun "not" not   , fun "&&" (&&)   , fun "||" (||)-  , con ([] :: [Bool])+  , unfun ([] :: [Bool])   , fun ":" ((:) :: Bool -> [Bool] -> [Bool]) --, fun "map" (map :: (Bool -> Bool) -> [Bool] -> [Bool])   , iif (undefined :: [Bool])@@ -192,9 +192,9 @@     ]    conjure "`access`" t7p-    [ con (0 :: Int)-    , con (1 :: Int)-    , con ([] :: [A])+    [ unfun (0 :: Int)+    , unfun (1 :: Int)+    , unfun ([] :: [A])     , fun ":" ((:) :: A -> [A] -> [A])     , fun "-" ((-) :: Int -> Int -> Int)     , fun "undefined" (undefined :: A)@@ -212,8 +212,8 @@   putStrLn "TerpreT benchmark #8: decrement elements\n"    conjure "decrelements" t8p-    [ con (1 :: Int)-    , con ([] :: [Int])+    [ unfun (1 :: Int)+    , unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "-" ((-) :: Int -> Int -> Int)     , fun "map" (map :: (Int -> Int) -> [Int] -> [Int])@@ -222,8 +222,8 @@   -- introduce lambdas    conjure "decrelements" t8p-    [ con (1 :: Int)-    , con ([] :: [Int])+    [ unfun (1 :: Int)+    , unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "-" ((-) :: Int -> Int -> Int)     , fun "map" (map :: (Int -> Int) -> [Int] -> [Int])
bench/unique.hs view
@@ -64,43 +64,43 @@   let n = 5    printUniqueCandidates (n+2) "foo" (undefined :: Int -> Int)-    [ con (0 :: Int)-    , con (1 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)     ]    printUniqueCandidates n "?" (undefined :: Int -> Int -> Int)-    [ con (0 :: Int)+    [ unfun (0 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "dec" (subtract 1 :: Int -> Int)     ]    printUniqueCandidates (n+2) "goo" (undefined :: [Int] -> [Int])-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     ]    printUniqueCandidates n "??" (undefined :: [Int] -> [Int] -> [Int])-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     ]    printUniqueCandidates (n+2) "ton" (undefined :: Bool -> Bool)-    [ con False-    , con True+    [ unfun False+    , unfun True     , fun "&&" (&&)     , fun "||" (||)     , fun "not" not     ]    printUniqueCandidates n "&|" (undefined :: Bool -> Bool -> Bool)-    [ con False-    , con True+    [ unfun False+    , unfun True     , fun "&&" (&&)     , fun "||" (||)     , fun "not" not
bench/weird.hs view
@@ -31,8 +31,8 @@  ingredients :: [Ingredient] ingredients  =-  [ con (0::Int)-  , con (1::Int)+  [ unfun (0::Int)+  , unfun (1::Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "*" ((*) :: Int -> Int -> Int)   , fun "==" ((==) :: Int -> Int -> Bool)
changelog.md view
@@ -2,6 +2,13 @@ ============================  +v0.7.4 (May 2025)+-----------------++* For now, `unfun` replaces `con`.+* Use list of properties in `conjureFromSpec`.++ v0.7.2 (May 2025) ----------------- 
code-conjure.cabal view
@@ -3,7 +3,7 @@ -- Copyright (C) 2021-2025 Rudy Matela -- Distributed under the 3-Clause BSD licence (see the file LICENSE). name:                code-conjure-version:             0.7.2+version:             0.7.4 synopsis:            synthesize Haskell functions out of partial definitions description:   Conjure is a tool that synthesizes Haskell functions out of partial definitions.@@ -69,7 +69,7 @@ source-repository this   type:            git   location:        https://github.com/rudymatela/conjure-  tag:             v0.7.2+  tag:             v0.7.4  library   exposed-modules: Conjure
eg/arith.hs view
@@ -48,8 +48,8 @@  ingredients :: [Ingredient] ingredients =-  [ con (0::Int)-  , con (1::Int)+  [ unfun (0::Int)+  , unfun (1::Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "*" ((*) :: Int -> Int -> Int)   ]
eg/bits.hs view
@@ -19,8 +19,8 @@ main :: IO () main  =  do   conjure "bitsum" bitsum-    [ con (0 :: Int)-    , con (1 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "halve" ((`div` 2) :: Int -> Int)     , fun "parity" ((`mod` 2) :: Int -> Int)     , fun "+" ((+) :: Int -> Int -> Int)@@ -29,9 +29,9 @@   -- bitsum n  =  parity n + bitsum (halve n)    conjure "bitsum" bitsum-    [ con (0 :: Int)-    , con (1 :: Int)-    , con (2 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)+    , unfun (2 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "`div`" (div :: Int -> Int -> Int)     , fun "`mod`" (mod :: Int -> Int -> Int)
eg/bools.hs view
@@ -25,8 +25,8 @@  ingredients :: [Ingredient] ingredients =-  [ con False-  , con True+  [ unfun False+  , unfun True   , fun "not" not   , fun "||" (||)   , fun "&&" (&&)
eg/bst.hs view
@@ -123,7 +123,7 @@ main :: IO () main = do   conjure "mem" mem-    [ con False+    [ unfun False     , fun "||" (||)     , fun "==" ((==) :: Int -> Int -> Bool)     , fun "<" ((<) :: Int -> Int -> Bool)@@ -131,15 +131,15 @@     ]    conjure "mem" mem-    [ con False-    , con True+    [ unfun False+    , unfun True     , fun "`compare`" (compare :: Int -> Int -> Ordering)     , ordcase (undefined :: Bool)     ]    -- simply out of reach performance-wise (reaching 16 but need size 22)   conjure "insert" insert-    [ con Leaf+    [ unfun Leaf     , fun "Node" Node     , fun "unit" unit     , fun "`compare`" (compare :: Int -> Int -> Ordering)@@ -150,7 +150,7 @@   -- reachable in 15s, candidate #32878 at size 14.   -- increase target to 50400 to reach...   conjureFromSpec "before" beforeSpec-    [ con Leaf+    [ unfun Leaf     , fun "Node" Node     , fun "==" ((==) :: Int -> Int -> Bool)     , fun "<" ((<) :: Int -> Int -> Bool)@@ -161,7 +161,7 @@   -- reachable in 14s, candidate #32747 at size 14.   -- increase target to 50400 to reach...   conjureFromSpec "beyond" beyondSpec-    [ con Leaf+    [ unfun Leaf     , fun "Node" Node     , fun "==" ((==) :: Int -> Int -> Bool)     , fun "<=" ((<) :: Int -> Int -> Bool)@@ -172,7 +172,7 @@   -- with 15, this reaches the solution, using 12 for shorter runtime   -- using maxEquationSize = 7 reduces runtime from 13s to 11s   conjureFromSpec "before" beforeSpec-    [ con Leaf+    [ unfun Leaf     , fun "Node" Node     , fun "`compare`" (compare :: Int -> Int -> Ordering)     , ordcase (undefined :: Tree)@@ -183,7 +183,7 @@   -- with 15, this reaches the solution, using 12 for shorter runtime   -- using maxEquationSize = 7 reduces runtime from 13s to 11s   conjureFromSpec "beyond" beyondSpec-    [ con Leaf+    [ unfun Leaf     , fun "Node" Node     , fun "`compare`" (compare :: Int -> Int -> Ordering)     , ordcase (undefined :: Tree)@@ -193,7 +193,7 @@    -- reachable in 55s, candidate #173109 at size 13.   conjure "union" union-    [ con Leaf+    [ unfun Leaf     , fun "Node" Node     , fun "before" before     , fun "beyond" beyond@@ -202,15 +202,15 @@   -- maybe with invariant following test data there will be more pruning   -- properties? -beforeSpec :: (Int -> Tree -> Tree) -> Bool-beforeSpec before  =  and-  [ holds n $ \x t -> ordered t ==> inorder (before x t) == takeWhile (< x) (inorder t)-  ] where n = 360+beforeSpec :: (Int -> Tree -> Tree) -> [Property]+beforeSpec before  =+  [ property $ \x t -> ordered t ==> inorder (before x t) == takeWhile (< x) (inorder t)+  ] -beyondSpec :: (Int -> Tree -> Tree) -> Bool-beyondSpec beyond  =  and-  [ holds n $ \x t -> ordered t ==> inorder (beyond x t) == dropWhile (<= x) (inorder t)-  ] where n = 360+beyondSpec :: (Int -> Tree -> Tree) -> [Property]+beyondSpec beyond  =+  [ property $ \x t -> ordered t ==> inorder (beyond x t) == dropWhile (<= x) (inorder t)+  ]  -- unionSpec :: (Int -> Tree -> Tree) -> Bool -- unionSpec union  =  and
eg/colin/IntFuns.hs view
@@ -15,7 +15,7 @@ triIngredients :: [Ingredient] triIngredients =   [ fun "==" ((==) :: Int -> Int -> Bool)-  , con (1::Int)+  , unfun (1::Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "dec" ((\x -> x-1) :: Int -> Int)   ]@@ -37,8 +37,8 @@ fibIngredients :: [Ingredient] fibIngredients =   [ fun "<=" ((<=) :: Int -> Int -> Bool)-  , con (0::Int)-  , con (1::Int)+  , unfun (0::Int)+  , unfun (1::Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "dec" ((\x -> x-1) :: Int -> Int)   ]@@ -79,7 +79,7 @@   [ fun "==" ((==) :: [Int] -> [Int] -> Bool)   , fun "factors" ((\n -> filter (\k -> n `mod` k == 0) [1..n]) :: Int -> [Int])   , fun "list2" ((\i j -> [i,j]) :: Int -> Int -> [Int])-  , con (1 :: Int)+  , unfun (1 :: Int)   ]  -- looking through 38 candidates, 100% match, 7/7 assignments
eg/colin/ListFuns.hs view
@@ -13,7 +13,7 @@  sumBackground :: [Ingredient] sumBackground =-  [ con (0::Int)+  [ unfun (0::Int)   , fun "+" ((+) :: Int -> Int -> Int)   ] @@ -44,7 +44,7 @@  memBackground :: [Ingredient] memBackground =-  [ con False+  [ unfun False   , fun "==" ((==) :: Int -> Int -> Bool)   , fun "&&" ((&&) :: Bool -> Bool -> Bool)   , fun "||" ((||) :: Bool -> Bool -> Bool)@@ -69,8 +69,8 @@  subBackground :: [Ingredient] subBackground  =-  [ con True-  , con False+  [ unfun True+  , unfun False   , fun ":" ((:) :: Int -> [Int] -> [Int])   , fun "==" ((==) :: Int -> Int -> Bool)   , iif (undefined :: Bool)@@ -112,9 +112,9 @@  takeBackground :: [Ingredient] takeBackground  =-  [ con (0 :: Int)-  , con (1 :: Int)-  , con ([] :: [A])+  [ unfun (0 :: Int)+  , unfun (1 :: Int)+  , unfun ([] :: [A])   , fun "-" ((-) :: Int -> Int -> Int)   , fun ":" ((:) :: A -> [A] -> [A])   ]@@ -134,9 +134,9 @@  dropBackground :: [Ingredient] dropBackground  =-  [ con (0 :: Int)-  , con (1 :: Int)-  , con ([] :: [A])+  [ unfun (0 :: Int)+  , unfun (1 :: Int)+  , unfun ([] :: [A])   , fun "-" ((-) :: Int -> Int -> Int)   ] @@ -155,7 +155,7 @@  ordBackground :: [Ingredient] ordBackground  =-  [ con True+  [ unfun True   , fun "null" (null :: [Int] -> Bool)   , fun "head" (head :: [Int] -> Int)   , fun "<=" ((<=) :: Int -> Int -> Bool)@@ -179,7 +179,7 @@ mergeBackground :: [Ingredient] mergeBackground  =   [ fun "<=" ((<=) :: Int -> Int -> Bool)-  , con ([] :: [Int])+  , unfun ([] :: [Int])   , fun ":" ((:) :: Int -> [Int] -> [Int])   , iif (undefined :: [Int])   ]@@ -197,7 +197,7 @@  zipBackground :: [Ingredient] zipBackground  =-  [ con ([] :: [(A,B)])+  [ unfun ([] :: [(A,B)])   , fun "(,)" ((,) :: A -> B -> (A,B))   , fun ":" ((:) :: (A,B) -> [(A,B)] -> [(A,B)])   ]@@ -214,7 +214,7 @@  assocsBackground :: [Ingredient] assocsBackground  =-  [ con ([] :: [A])+  [ unfun ([] :: [A])   , fun "==" ((==) :: Int -> Int -> Bool)   , fun ":" ((:) :: A -> [A] -> [A])   , fun "fst" (fst :: (Int,A) -> Int)
eg/count.hs view
@@ -38,8 +38,8 @@   -- count x []  =  0   -- count x (y:xs)  =  count x xs + (if x == y then 1 else 0)   conjure "count" count'-    [ con (0 :: Int)-    , con (1 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "==" ((==) :: A -> A -> Bool)     , iif (undefined :: Int)@@ -48,8 +48,8 @@   -- a little bit larger, guards are only allowed at the root   -- so there is a need to repeat the recursive call twice   conjure "count" count'-    [ con (0 :: Int)-    , con (1 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "==" ((==) :: A -> A -> Bool)     , guard
eg/dupos.hs view
@@ -3,7 +3,6 @@ -- Copyright (C) 2021-2025 Rudy Matela -- Distributed under the 3-Clause BSD licence (see the file LICENSE). import Conjure-import Test.LeanCheck  -- needed for duplicatesSpec only  duplicates :: [Int] -> [Int] -- Eq a => [a] -> [a] duplicates []  =  []@@ -22,10 +21,10 @@ duplicates' [1,0,1,0,1]  =  [0,1] duplicates' [0,1,2,1]  =  [1] -duplicatesSpec :: ([Int] -> [Int]) -> Bool-duplicatesSpec duplicates  =  and-  [ holds 360 $ \x xs -> (count (x ==) xs > 1) == elem x (duplicates xs)-  , holds 360 $ \x xs -> count (x ==) (duplicates xs) <= 1+duplicatesSpec :: ([Int] -> [Int]) -> [Property]+duplicatesSpec duplicates  =+  [ property $ \x xs -> (count (x ==) xs > 1) == elem x (duplicates xs)+  , property $ \x xs -> count (x ==) (duplicates xs) <= 1   ]  where  count p  =  length . filter p  positionsFrom :: Int -> Int -> [Int] -> [Int]@@ -53,7 +52,7 @@   --                       else duplicates xs                              -- 17   -- within reach performance wise.   conjure "duplicates" duplicates'-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun "not" not     , fun "&&" (&&)     , fun ":" ((:) :: Int -> [Int] -> [Int])@@ -62,7 +61,7 @@     ]    conjureFromSpec "duplicates" duplicatesSpec-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun "not" not     , fun "&&" (&&)     , fun ":" ((:) :: Int -> [Int] -> [Int])@@ -71,14 +70,11 @@     ]    conjure "positionsFrom" positionsFrom'-    [ con ([] :: [Int])-    , con (1 :: Int)+    [ unfun ([] :: [Int])+    , unfun (1 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "==" ((==) :: A -> A -> Bool)----  , iif (undefined :: [Int])-    -- cheat codes:-    , fun "id" (id :: [Int] -> [Int])-    , iif (undefined :: [Int] -> [Int])+    , guard+    , target 1080 -- 100800 -- can find after 44472 candidates in 25s     ]
eg/dupos.txt view
@@ -51,7 +51,7 @@  positionsFrom :: Int -> A -> [A] -> [Int] -- testing 360 combinations of argument values--- pruning with 5/10 rules+-- pruning with 6/11 rules -- 1 candidates of size 1 -- 0 candidates of size 2 -- 2 candidates of size 3@@ -61,12 +61,10 @@ -- 34 candidates of size 7 -- 0 candidates of size 8 -- 133 candidates of size 9--- 0 candidates of size 10+-- 8 candidates of size 10 -- 510 candidates of size 11--- 16 candidates of size 12--- 1947 candidates of size 13--- 104 candidates of size 14--- tested 2653 candidates-positionsFrom x y []  =  []-positionsFrom x y (z:xs)  =  (if y == z then (x :) else id) (positionsFrom (x + 1) y xs)+-- 40 candidates of size 12+-- 1943 candidates of size 13+-- tested 2678 candidates+positionsFrom  =  undefined  -- search exhausted 
eg/either.hs view
@@ -30,12 +30,12 @@ fromRight' 0 (Right 1)  =  1 fromRight' 1 (Right 0)  =  0 -eitherSpec :: ((A -> A) -> (A -> A) -> Either A A -> A) -> Bool-eitherSpec either  =  and-  [ either (+1) (+2) (Left 0) == 1-  , either (+1) (+2) (Right 0) == 2-  , either (*10) (*100) (Left 1) == 10-  , either (*10) (*100) (Right 2) == 200+eitherSpec :: ((A -> A) -> (A -> A) -> Either A A -> A) -> [Property]+eitherSpec either  =+  [ property $ either (+1) (+2) (Left 0) == 1+  , property $ either (+1) (+2) (Right 0) == 2+  , property $ either (*10) (*100) (Left 1) == 10+  , property $ either (*10) (*100) (Right 2) == 200   ]  lefts' :: [Either A A] -> [A]@@ -59,9 +59,9 @@   [ fun "Left"  (Left :: A -> Either A A)   , fun "Right" (Right :: A -> Either A A) -  , con False-  , con True+  , unfun False+  , unfun True -  , con ([] :: [A])+  , unfun ([] :: [A])   , fun ":" ((:) :: A -> [A] -> [A])   ]
eg/factorial.hs view
@@ -15,8 +15,8 @@ main  =  do   -- explicit recursion   conjure "factorial n" factorial-    [ con (0::Int)-    , con (1::Int)+    [ unfun (0::Int)+    , unfun (1::Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)@@ -27,8 +27,8 @@    -- using foldr and enumFromTo   conjure "factorial n" factorial-    [ con (0::Int)-    , con (1::Int)+    [ unfun (0::Int)+    , unfun (1::Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)
eg/fib01.hs view
@@ -31,7 +31,7 @@   -- Found!  It takes about 12 seconds to run with maxSize=8   -- running with maxSize = 5 for faster runtime   conjure "fib01" fib01-    [ con (0::Int)+    [ unfun (0::Int)     , fun "dec" (subtract 1 :: Int -> Int)     , fun "+" ((+) :: Int -> Int -> Int)     , maxSize 5@@ -41,7 +41,7 @@   -- It takes about 27 seconds to run with maxSize=12   -- running with maxSize = 9 for faster runtime   conjure "fib01" fib01-    [ con (0::Int)+    [ unfun (0::Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "dec" (subtract 1 :: Int -> Int)     , fun "<=" ((<=) :: Int -> Int -> Bool)
eg/fibonacci.hs view
@@ -16,9 +16,9 @@ main :: IO () main  =  do   conjure "fibonacci n" fibonacci-    [ con (0::Int)-    , con (1::Int)-    , con (2::Int)+    [ unfun (0::Int)+    , unfun (1::Int)+    , unfun (2::Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)     ]
eg/gcd.hs view
@@ -19,7 +19,7 @@  main :: IO () main = conjure "gcd a b" gcd'-  [ con (0::Int)+  [ unfun (0::Int)   , fun "`mod`" (mod :: Int -> Int -> Int)   ]   -- desired function:
eg/higher.hs view
@@ -4,36 +4,48 @@ -- Distributed under the 3-Clause BSD licence (see the file LICENSE). import Conjure -appSpec :: ((Int -> Int) -> Int -> Int) -> Bool-appSpec ($)  =  ((+1) $ 2) == 3-             && (abs $ (-2)) == 2-             && (negate $ 1) == -1+appSpec :: ((Int -> Int) -> Int -> Int) -> [Property]+appSpec ($)  =+  [ property (((+1) $ 2) == 3)+  , property ((abs $ (-2)) == 2)+  , property ((negate $ 1) == -1)+  ] -composeSpec :: ((Int->Int) -> (Int->Int) -> Int->Int) -> Bool-composeSpec (.)  =  ((*2) . (*3)) 1 == 6-                 && (abs . negate) 7 == 7-                 && (negate . abs) 8 == -8+composeSpec :: ((Int->Int) -> (Int->Int) -> Int->Int) -> [Property]+composeSpec (.)  =+  [ property $ ((*2) . (*3)) 1 == 6+  , property $ (abs . negate) 7 == 7+  , property $ (negate . abs) 8 == -8+  ] -flipSpec :: ((Int -> Int -> Int) -> Int -> Int -> Int) -> Bool-flipSpec flip  =  flip const 1 2 == 2-               && flip div 2 10 == 5-               && flip mod 3 10 == 1+flipSpec :: ((Int -> Int -> Int) -> Int -> Int -> Int) -> [Property]+flipSpec flip  =+  [ property $ flip const 1 2 == 2+  , property $ flip div 2 10 == 5+  , property $ flip mod 3 10 == 1+  ] -mapSpec :: ((Int -> Int) -> [Int] -> [Int]) -> Bool-mapSpec map  =  map (*2) [1,2,3] == [2,4,6]-             && map abs [0,-1,-2] == [0,1,2]+mapSpec :: ((Int -> Int) -> [Int] -> [Int]) -> [Property]+mapSpec map  =+  [ property $ map (*2) [1,2,3] == [2,4,6]+  , property $ map abs [0,-1,-2] == [0,1,2]+  ] -foldSpec :: ((Int -> Int -> Int) -> Int -> [Int] -> Int) -> Bool-foldSpec fold  =  fold (+) 0 [1,2,3] == 6-               && fold (*) 1 [1,2,3] == 6-               && fold (+) 0 [1,2,3,4] == 10-               && fold (*) 1 [1,2,3,4] == 24+foldSpec :: ((Int -> Int -> Int) -> Int -> [Int] -> Int) -> [Property]+foldSpec fold  =+  [ property $ fold (+) 0 [1,2,3] == 6+  , property $ fold (*) 1 [1,2,3] == 6+  , property $ fold (+) 0 [1,2,3,4] == 10+  , property $ fold (*) 1 [1,2,3,4] == 24+  ] -filterSpec :: ((Int -> Bool) -> [Int] -> [Int]) -> Bool-filterSpec filter  =  filter (<0) [0,1,-1,2,-2] == [-1,-2]-                   && filter (>0) [0,1,-1,2,-2] == [1,2]-                   && filter odd [0,1,2,3,4,5,6] == [1,3,5]-                   && filter even [0,1,2,3,4,5,6] == [0,2,4,6]+filterSpec :: ((Int -> Bool) -> [Int] -> [Int]) -> [Property]+filterSpec filter  =+  [ property $ filter (<0) [0,1,-1,2,-2] == [-1,-2]+  , property $ filter (>0) [0,1,-1,2,-2] == [1,2]+  , property $ filter odd [0,1,2,3,4,5,6] == [1,3,5]+  , property $ filter even [0,1,2,3,4,5,6] == [0,2,4,6]+  ]  main :: IO () main = do@@ -47,7 +59,7 @@  ingredients :: [Ingredient] ingredients  =-  [ con ([] :: [Int])+  [ unfun ([] :: [Int])   , fun ":" ((:) :: Int -> [Int] -> [Int])   , guard   ]
eg/ints.hs view
@@ -3,6 +3,7 @@ -- Copyright (C) 2021-2025 Rudy Matela -- Distributed under the 3-Clause BSD licence (see the file LICENSE). import Conjure+import Prelude hiding (sum, product)  second :: [Int] -> Int second [x,y]  =  y@@ -13,51 +14,51 @@ third [x,y,z]  =  z third [x,y,z,w]  =  z -sum' :: [Int] -> Int-sum' [x]      =  x-sum' [x,y]    =  x+y-sum' [x,y,z]  =  x+y+z+sum :: [Int] -> Int+sum [1]  =  1+sum [1,2]  =  3+sum [1,2,3]  =  6 -product' :: [Int] -> Int-product' [x]      =  x-product' [x,y]    =  x*y-product' [x,y,z]  =  x*y*z+product :: [Int] -> Int+product [1]  =  1+product [1,2]  =  2+product [1,2,3]  =  6  main :: IO () main = do-  conjure "second"  (second :: [Int] -> Int)+  conjure "second" second     [ fun "null" (null :: [Int] -> Bool)     , fun "head" (head :: [Int] -> Int)     , fun "tail" (tail :: [Int] -> [Int])     ] -  conjure "third"   (third :: [Int] -> Int)+  conjure "third" third     [ fun "null" (null :: [Int] -> Bool)     , fun "head" (head :: [Int] -> Int)     , fun "tail" (tail :: [Int] -> [Int])     ] -  conjure "sum"     (sum' :: [Int] -> Int)-    [ con (0 :: Int)-    , con (1 :: Int)+  conjure "sum" sum+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     ] -  conjure "product" (product' :: [Int] -> Int)-    [ con (0 :: Int)-    , con (1 :: Int)+  conjure "product" product+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     ] -  conjure "sum"     (sum' :: [Int] -> Int) ingredientsWithFold-  conjure "product" (product' :: [Int] -> Int) ingredientsWithFold+  conjure "sum"     sum     ingredientsWithFold+  conjure "product" product ingredientsWithFold  ingredients :: [Ingredient] ingredients =-  [ con (0 :: Int)-  , con (1 :: Int)+  [ unfun (0 :: Int)+  , unfun (1 :: Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "*" ((*) :: Int -> Int -> Int)   ]
eg/ints.txt view
@@ -18,7 +18,7 @@ third xs  =  head (tail (tail xs))  sum :: [Int] -> Int--- testing 360 combinations of argument values+-- testing 3 combinations of argument values -- pruning with 14/25 rules -- 2 candidates of size 1 -- 0 candidates of size 2@@ -30,7 +30,7 @@ sum (x:xs)  =  x + sum xs  product :: [Int] -> Int--- testing 360 combinations of argument values+-- testing 3 combinations of argument values -- pruning with 14/25 rules -- 2 candidates of size 1 -- 0 candidates of size 2@@ -42,7 +42,7 @@ product (x:xs)  =  x * product xs  sum :: [Int] -> Int--- testing 360 combinations of argument values+-- testing 3 combinations of argument values -- pruning with 15/26 rules -- 2 candidates of size 1 -- 0 candidates of size 2@@ -52,7 +52,7 @@ sum  =  foldr (+) 0  product :: [Int] -> Int--- testing 360 combinations of argument values+-- testing 3 combinations of argument values -- pruning with 15/26 rules -- 2 candidates of size 1 -- 0 candidates of size 2
eg/list.hs view
@@ -27,9 +27,9 @@   | z <= y && y <= x  =  [z,y,x]  (+++) :: [Int] -> [Int] -> [Int]-[x]     +++ [y]      =  [x,y]-[x,y]   +++ [z,w]    =  [x,y,z,w]-[x,y,z] +++ [w,v,u]  =  [x,y,z,w,v,u]+[1]     +++ [2]      =  [1,2]+[1,2]   +++ [0,1]    =  [1,2,0,1]+[0,1,0] +++ [1,0,1]  =  [0,1,0,1,0,1]  (\/) :: [Int] -> [Int] -> [Int] [x] \/ [y]  =  [x,y]@@ -56,30 +56,30 @@ main :: IO () main = do   conjure "length" length'-    [ con (0 :: Int)-    , con (1 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     ]    conjure "reverse" reverse'-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     ]    conjure "++" (+++)-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     ]    conjure "++" (+++)-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "foldr" (foldr :: (Int -> [Int] -> [Int]) -> [Int] -> [Int] -> [Int])     ]    conjure "last" last'-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "null" (null :: [Int] -> Bool)     , guard@@ -87,26 +87,26 @@     ]    conjure "last" last'-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "undefined" (undefined :: Int)     , maxPatternDepth 2     ]    conjure "zip" (zip')-    [ con ([] :: [(Int,Int)])+    [ unfun ([] :: [(Int,Int)])     , fun ":" ((:) :: (Int,Int) -> [(Int,Int)] -> [(Int,Int)])     , fun "," ((,) :: Int -> Int -> (Int,Int))     ]    conjure "\\/" (\/)-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     ]    conjure "ordered" ordered'-    [ con False-    , con True+    [ unfun False+    , unfun True     , fun "&&" (&&)     , fun "||" (||)     , fun "<=" ((<=) :: Int -> Int -> Bool)
eg/list.txt view
@@ -25,7 +25,7 @@ reverse (x:xs)  =  reverse xs ++ [x]  (++) :: [Int] -> [Int] -> [Int]--- testing 360 combinations of argument values+-- testing 3 combinations of argument values -- pruning with 0/0 rules -- 3 candidates of size 1 -- 0 candidates of size 2@@ -38,7 +38,7 @@ (x:xs) ++ ys  =  x:(xs ++ ys)  (++) :: [Int] -> [Int] -> [Int]--- testing 360 combinations of argument values+-- testing 3 combinations of argument values -- pruning with 2/2 rules -- 3 candidates of size 1 -- 0 candidates of size 2
eg/maybe.hs view
@@ -20,12 +20,12 @@ fromMaybe' 0 (Just 1)  =  1 fromMaybe' 1 (Just 2)  =  2 -maybeSpec :: (A -> (A -> A) -> Maybe A -> A) -> Bool-maybeSpec maybe  =  and-  [ maybe 0 undefined Nothing == 0-  , maybe 1 undefined Nothing == 1-  , maybe undefined (+1) (Just 1) == 2-  , maybe undefined (*2) (Just 3) == 6+maybeSpec :: (A -> (A -> A) -> Maybe A -> A) -> [Property]+maybeSpec maybe  =+  [ property $ maybe 0 undefined Nothing == 0+  , property $ maybe 1 undefined Nothing == 1+  , property $ maybe undefined (+1) (Just 1) == 2+  , property $ maybe undefined (*2) (Just 3) == 6   ]  listToMaybe' :: [A] -> Maybe A@@ -61,13 +61,13 @@  ingredients :: [Ingredient] ingredients  =-  [ con (Nothing :: Maybe A)+  [ unfun (Nothing :: Maybe A)   , fun "Just" (Just :: A -> Maybe A) -  , con False-  , con True+  , unfun False+  , unfun True -  , con ([] :: [A])+  , unfun ([] :: [A])   , fun ":" ((:) :: A -> [A] -> [A])   ] 
eg/oddeven.hs view
@@ -30,21 +30,21 @@  ingredients1 :: [Ingredient] ingredients1 =-  [ con (0::Int)-  , con (1::Int)-  , con (2::Int)+  [ unfun (0::Int)+  , unfun (1::Int)+  , unfun (2::Int)   , fun "+" ((+) :: Int -> Int -> Int)    , fun "-" ((-) :: Int -> Int -> Int)-  , con False-  , con True+  , unfun False+  , unfun True   ]  ingredients2 :: [Ingredient] ingredients2 =-  [ con (0::Int)-  , con (1::Int)-  , con (2::Int)+  [ unfun (0::Int)+  , unfun (1::Int)+  , unfun (2::Int)   , fun "+" ((+) :: Int -> Int -> Int)    , fun "`mod`" (mod :: Int -> Int -> Int)
eg/peano.hs view
@@ -27,13 +27,13 @@ main :: IO () main  =  do   conjure "+" plus-    [ con Z+    [ unfun Z     , fun "S" S     ]    -- use + to conjure *   conjure "*" times-    [ con Z+    [ unfun Z     , fun "S" S     , fun "+" (let p + Z    =  p                    p + S q  =  S p + q
eg/pow.hs view
@@ -16,8 +16,8 @@   -- pow x 0  =  1   -- pow x y  =  x * pow x (y - 1)   conjure "pow" pow-    [ con (0::Int)-    , con (1::Int)+    [ unfun (0::Int)+    , unfun (1::Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)     ]@@ -27,8 +27,8 @@   --             2   3  4     5  6 7   8  9    10 11 12 13 14     15     16   -- out of reach performance wise, OOM at size 9   conjure "pow" pow-    [ con (0::Int)-    , con (1::Int)+    [ unfun (0::Int)+    , unfun (1::Int) --  , fun "sq" ((\x -> x*x) :: Int -> Int) -- cheat! OOM still     , fun "*" ((*) :: Int -> Int -> Int)     , fun "halve" ((`div` 2) :: Int -> Int)
eg/replicate.hs view
@@ -26,10 +26,10 @@ main :: IO () main = do   conjure "replicate" replicate'-    [ con (0 :: Int)-    , con (1 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "-" ((-) :: Int -> Int -> Int)-    , con ""+    , unfun ""     , fun ":" ((:) :: Char -> String -> String)     ] @@ -49,7 +49,7 @@    -- alternative generation using recursion   conjure "replicates" replicates'-    [ con ""+    [ unfun ""     , fun ":" ((:) :: Char -> String -> String)     , fun "++" ((++) :: String -> String -> String)     , fun "replicate" (replicate :: Int -> Char -> String)
eg/setelem.hs view
@@ -19,23 +19,19 @@ main :: IO () main = do   conjure "elem" (elem')-    [ con True-    , con False+    [ unfun True+    , unfun False     , fun "||" (||)     , fun "&&" (&&)     , fun "not" not-    , con ([] :: [Int])-    , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "==" ((==) :: Int -> Int -> Bool)     ]    conjure "set" (set')-    [ con True-    , con False+    [ unfun True+    , unfun False     , fun "||" (||)     , fun "&&" (&&)     , fun "not" not-    , con ([] :: [Int])-    , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "elem" (elem :: Int -> [Int] -> Bool)     ]
eg/setelem.txt view
@@ -15,7 +15,7 @@  set :: [Int] -> Bool -- testing 4 combinations of argument values--- pruning with 41/52 rules+-- pruning with 39/49 rules -- 2 candidates of size 1 -- 0 candidates of size 2 -- 0 candidates of size 3
eg/sort.hs view
@@ -47,7 +47,7 @@   -- sort []  =  []   -- sort (x:xs)  =  insert x (sort xs)   conjure "sort" sort'-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun "insert" (insert :: Int -> [Int] -> [Int])     , fun "head" (head :: [Int] -> Int)     , fun "tail" (tail :: [Int] -> [Int])@@ -57,7 +57,7 @@   -- now through fold   -- sort xs  =  foldr insert [] xs   conjure "sort" sort'-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun "insert" (insert :: Int -> [Int] -> [Int])     , fun "foldr" (foldr :: (Int -> [Int] -> [Int]) -> [Int] -> [Int] -> [Int])     ]@@ -78,7 +78,7 @@   -- but is not generated because of the deconstruction restriction.   -- The following does generate a correct but inneficient version of qsort.   conjure "qsort" sort'-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     , fun "<=" ((<=) :: Int -> Int -> Bool)@@ -89,7 +89,7 @@   -- if we disable the descent requirement, we get the efficient qsort   -- though with a larger search space   conjure "qsort" sort'-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     , fun "<=" ((<=) :: Int -> Int -> Bool)@@ -106,7 +106,7 @@   --   | otherwise  =  merge (y:x:xs) ys   -- set target to 2 000 000 to reach it   conjure "merge" merge'-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "<=" ((<=) :: Int -> Int -> Bool)     , guard
eg/spec.hs view
@@ -6,46 +6,52 @@ import Prelude hiding (sum)  -squareSpec :: (Int -> Int) -> Bool-squareSpec square  =  square 0 == 0-                   && square 1 == 1-                   && square 2 == 4+squareSpec :: (Int -> Int) -> [Property]+squareSpec square  =+  [ property $ square 0 == 0+  , property $ square 1 == 1+  , property $ square 2 == 4+  ]  squareIngredients :: [Ingredient] squareIngredients  =-  [ con (0::Int)-  , con (1::Int)+  [ unfun (0::Int)+  , unfun (1::Int)   , fun "+" ((+) :: Int -> Int -> Int)   , fun "*" ((*) :: Int -> Int -> Int)   ] -squarePropertySpec :: (Int -> Int) -> Bool-squarePropertySpec square  =  and-  [ holds n $ \x -> square x >= x-  , holds n $ \x -> square x >= 0-  , exists n $ \x -> square x > x-  ]  where  n = 60+squarePropertySpec :: (Int -> Int) -> [Property]+squarePropertySpec square  =+  [ property $ \x -> square x >= x+  , property $ \x -> square x >= 0+  , property $ square 2 == 4+  ]  -sumSpec :: ([Int] -> Int) -> Bool-sumSpec sum  =  sum []      == 0-             && sum [1,2]   == 3-             && sum [3,4,5] == 12+sumSpec :: ([Int] -> Int) -> [Property]+sumSpec sum  =+  [ property $ sum []      == 0+  , property $ sum [1,2]   == 3+  , property $ sum [3,4,5] == 12+  ]  sumIngredients :: [Ingredient] sumIngredients  =   [ fun "null" (null :: [Int] -> Bool)-  , con (0::Int)+  , unfun (0::Int)   , fun "+"    ((+) :: Int -> Int -> Int)   , fun "head" (head :: [Int] -> Int)   , fun "tail" (tail :: [Int] -> [Int])   ]  -appSpec :: ([Int] -> [Int] -> [Int]) -> Bool-appSpec (++)  =  []      ++ [0,1]   == [0,1]-              && [2,3]   ++ []      == [2,3]-              && [4,5,6] ++ [7,8,9] == [4,5,6,7,8,9]+appSpec :: ([Int] -> [Int] -> [Int]) -> [Property]+appSpec (++)  =+  [ property $ []      ++ [0,1]   == [0,1]+  , property $ [2,3]   ++ []      == [2,3]+  , property $ [4,5,6] ++ [7,8,9] == [4,5,6,7,8,9]+  ]  appIngredients :: [Ingredient] appIngredients =
eg/subset.hs view
@@ -44,9 +44,9 @@   -- subset [] ys  =  True   -- subset (x:xs) ys  =  elem x ys && subset xs ys   conjure "subset" (subset')-    [ con ([] :: [Int])-    , con True-    , con False+    [ unfun ([] :: [Int])+    , unfun True+    , unfun False     , fun "&&" (&&)     , fun "||" (||)     , fun "elem" (elem :: Int -> [Int] -> Bool)
eg/take-drop.hs view
@@ -27,9 +27,9 @@   -- drop x []  =  []                   -- 2   -- drop x (y:xs)  =  drop (x - 1) xs  -- 7   conjure "drop" (drop' :: Int -> [A] -> [A])-    [ con (0 :: Int)-    , con (1 :: Int)-    , con ([] :: [A])+    [ unfun (0 :: Int)+    , unfun (1 :: Int)+    , unfun ([] :: [A])     , fun ":" ((:) :: A -> [A] -> [A])     , fun "-" ((-) :: Int -> Int -> Int)     ]@@ -38,9 +38,9 @@   -- take x []  =  []                     -- 2   -- take x (y:xs)  =  y:take (x - 1) xs  -- 9   conjure "take" (take' :: Int -> [A] -> [A])-    [ con (0 :: Int)-    , con (1 :: Int)-    , con ([] :: [A])+    [ unfun (0 :: Int)+    , unfun (1 :: Int)+    , unfun ([] :: [A])     , fun "-" ((-) :: Int -> Int -> Int)     , fun ":" ((:) :: A -> [A] -> [A])     ]
eg/tapps.hs view
@@ -27,8 +27,8 @@  ingredients :: [Ingredient] ingredients =-  [ con (0 :: Int)-  , con (1 :: Int)+  [ unfun (0 :: Int)+  , unfun (1 :: Int) #if __GLASGOW_HASKELL__ < 800   , fun "+" ((+) :: Int -> Int -> Int)   , fun "*" ((*) :: Int -> Int -> Int)
eg/these.hs view
@@ -78,12 +78,12 @@     ]    conjure "listhese" listhese'-    [ con ([] :: [A])+    [ unfun ([] :: [A])     , fun ":" ((:) :: A -> [A] -> [A])     ]    conjure "cathis" cathis'-    [ con ([] :: [A])+    [ unfun ([] :: [A])     , fun ":" ((:) :: A -> [A] -> [A])     , fun "isThis" (isThis :: These A B -> Bool)     , fun "fromThis" (fromThis :: These A B -> A)@@ -91,7 +91,7 @@     ]    conjure "cathat" cathat'-    [ con ([] :: [B])+    [ unfun ([] :: [B])     , fun ":" ((:) :: B -> [B] -> [B])     , fun "isThat" (isThat :: These A B -> Bool)     , fun "fromThat" (fromThat :: These A B -> B)@@ -99,19 +99,19 @@     ]    conjure "cathis" cathis'-    [ con ([] :: [A])+    [ unfun ([] :: [A])     , fun ":" ((:) :: A -> [A] -> [A])     , maxPatternDepth 2     ]    conjure "cathat" cathat'-    [ con ([] :: [B])+    [ unfun ([] :: [B])     , fun ":" ((:) :: B -> [B] -> [B])     , maxPatternDepth 2     ]    conjure "cathese" cathese'-    [ con ([] :: [A])+    [ unfun ([] :: [A])     , fun ":" ((:) :: A -> [A] -> [A])     , maxPatternDepth 2     ]
eg/tree.hs view
@@ -109,31 +109,31 @@     ]    conjure "size" size-    [ con (0 :: Int)-    , con (1 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "nil" nil     ]    conjure "height" height-    [ con (0 :: Int)-    , con (1 :: Int)-    , con (-1 :: Int)+    [ unfun (0 :: Int)+    , unfun (1 :: Int)+    , unfun (-1 :: Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "max" (max :: Int -> Int -> Int)     , fun "nil" nil     ]    conjure "mem" mem-    [ con False+    [ unfun False     , fun "||" (||)     , fun "==" ((==) :: Int -> Int -> Bool)     ]    -- unreachable: needs size 22 but OOMs at 19/20 (v0.5.16)   conjure "ordered" ordered-    [ con True-    , con False+    [ unfun True+    , unfun False     , fun "&&" (&&)     , fun "||" (||)     , fun "<" ((<) :: Int -> Int -> Bool)@@ -149,19 +149,19 @@     ]    conjure "preorder" preorder-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     ]    conjure "inorder" inorder-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     ]    conjure "posorder" posorder-    [ con ([] :: [Int])+    [ unfun ([] :: [Int])     , fun ":" ((:) :: Int -> [Int] -> [Int])     , fun "++" ((++) :: [Int] -> [Int] -> [Int])     ]
eg/tri.hs view
@@ -12,7 +12,7 @@ main :: IO () main  =  do   conjure "tri" tri-    [ con (1::Int)+    [ unfun (1::Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)     ]
eg/tuple.hs view
@@ -31,24 +31,20 @@  type Curry a b c  =  ((a,b) -> c) -> (a -> b -> c) -currySpec :: Curry A A A -> Bool-currySpec curry  =  and-  [ holds n $ \x y -> curry fst x y == x-  , holds n $ \x y -> curry snd x y == y-  , holds n $ \x y -> curry (\(i,j) -> i + j) x y == x + y+currySpec :: Curry A A A -> [Property]+currySpec curry  =+  [ property $ \x y -> curry fst x y == x+  , property $ \x y -> curry snd x y == y+  , property $ \x y -> curry (\(i,j) -> i + j) x y == x + y   ]-  where-  n = 360  type Uncurry a b c  =  (a -> b -> c) -> ((a,b) -> c) -uncurrySpec :: Uncurry A A A -> Bool-uncurrySpec uncurry  =  and-  [ holds n $ \x y -> uncurry (+) (x,y) == x + y-  , holds n $ \x y -> uncurry (*) (x,y) == x * y+uncurrySpec :: Uncurry A A A -> [Property]+uncurrySpec uncurry  =+  [ property $ \x y -> uncurry (+) (x,y) == x + y+  , property $ \x y -> uncurry (*) (x,y) == x * y   ]-  where-  n = 360   -- now two functions that are a bit more interesting:
mk/depend.mk view
@@ -978,7 +978,12 @@   src/Conjure/Defn.hs \   src/Conjure/Conjurable.hs src/Conjure/Settings.o: \-  src/Conjure/Settings.hs+  src/Conjure/Utils.hs \+  src/Conjure/Settings.hs \+  src/Conjure/Ingredient.hs \+  src/Conjure/Expr.hs \+  src/Conjure/Defn.hs \+  src/Conjure/Conjurable.hs src/Conjure/Utils.o: \   src/Conjure/Utils.hs test/conjurable.o: \
src/Conjure.hs view
@@ -19,8 +19,8 @@ -- -- > ingredients :: [Ingredient] -- > ingredients =--- >   [ con (0::Int)--- >   , con (1::Int)+-- >   [ unfun (0::Int)+-- >   , unfun (1::Int) -- >   , fun "+" ((+) :: Int -> Int -> Int) -- >   , fun "*" ((*) :: Int -> Int -> Int) -- >   , fun "-" ((-) :: Int -> Int -> Int)@@ -62,9 +62,9 @@ -- > take' 3 [x,y]  =  [x,y] -- -- > > conjure "take" (take' :: Int -> [A] -> [A])--- > >   [ con (0 :: Int)--- > >   , con (1 :: Int)--- > >   , con ([] :: [A])+-- > >   [ unfun (0 :: Int)+-- > >   , unfun (1 :: Int)+-- > >   , unfun ([] :: [A]) -- > >   , fun ":" ((:) :: A -> [A] -> [A]) -- > >   , fun "-" ((-) :: Int -> Int -> Int) -- > >   ]@@ -95,9 +95,8 @@ -- * Basic use     conjure   , Ingredient-  , con-  , unfun   , fun+  , unfun   , guard   , iif   , ordcase@@ -109,6 +108,8 @@  -- * Conjuring from a specification   , conjureFromSpec+  , Property+  , property  -- * When using custom types   , Conjurable (conjureExpress, conjureEquality, conjureTiers, conjureCases, conjureSubTypes, conjureSize)@@ -163,6 +164,7 @@   , Prim   , pr   , prim+  , con   ) where 
src/Conjure/Engine.hs view
@@ -52,10 +52,15 @@   , nonAtomicNumbers   , uniqueCandidates +  -- * Properties+  , Property+  , property+   -- * other modules   , module Data.Express   , module Data.Express.Fixtures   , module Conjure.Reason+  , module Conjure.Ingredient   ) where @@ -96,8 +101,8 @@ -- > -- > ingredients :: [Ingredient] -- > ingredients  =--- >   [ con (0::Int)--- >   , con (1::Int)+-- >   [ unfun (0::Int)+-- >   , unfun (1::Int) -- >   , fun "+" ((+) :: Int -> Int -> Int) -- >   , fun "*" ((*) :: Int -> Int -> Int) -- >   , fun "-" ((-) :: Int -> Int -> Int)@@ -116,22 +121,24 @@ -- > factorial 0  =  1 -- > factorial x  =  x * factorial (x - 1) ----- The ingredients list is defined with 'con' and 'fun'.+-- The ingredients list is defined with 'unfun' and 'fun'. conjure :: Conjurable f => String -> f -> [Ingredient] -> IO ()-conjure nm f  =  conjure0 nm f (const True)+conjure nm f  =  conjure0 nm f (const [])   -- | Conjures an implementation from a function specification. -- -- This function works like 'conjure' but instead of receiving a partial definition--- it receives a boolean filter / property about the function.+-- it receives a collection of test properties about the function. -- -- For example, given: ----- > squareSpec :: (Int -> Int) -> Bool--- > squareSpec square  =  square 0 == 0--- >                    && square 1 == 1--- >                    && square 2 == 4+-- > squarePropertySpec :: (Int -> Int) -> [Property]+-- > squarePropertySpec square  =+-- >   [ property $ \x -> square x >= x+-- >   , property $ \x -> square x >= 0+-- >   , property $ square 2 == 4+-- >   ] -- -- Then: --@@ -143,19 +150,7 @@ -- > -- 0.1s, 1 candidates of size 3 -- > -- 0.1s, tested 2 candidates -- > square x  =  x * x------ This allows users to specify QuickCheck-style properties,--- here is an example using LeanCheck:------ > import Test.LeanCheck (holds, exists)--- >--- > squarePropertySpec :: (Int -> Int) -> Bool--- > squarePropertySpec square  =  and--- >   [ holds n $ \x -> square x >= x--- >   , holds n $ \x -> square x >= 0--- >   , exists n $ \x -> square x > x--- >   ]  where  n = 60-conjureFromSpec :: Conjurable f => String -> (f -> Bool) -> [Ingredient] -> IO ()+conjureFromSpec :: Conjurable f => String -> (f -> [Property]) -> [Ingredient] -> IO () conjureFromSpec nm p  =  conjure0 nm undefined p  @@ -163,7 +158,7 @@ --   function specification. -- --   This works like the functions 'conjure' and 'conjureFromSpec' combined.-conjure0 :: Conjurable f => String -> f -> (f -> Bool) -> [Ingredient] -> IO ()+conjure0 :: Conjurable f => String -> f -> (f -> [Property]) -> [Ingredient] -> IO () conjure0 nm f p es  =  do   -- the code section below became quite ugly with time and patches.   -- it is still maintainable and readable as it is, but perhaps@@ -176,7 +171,7 @@       putStrLn $ "{-"       putStr $ showDefn ts       putStrLn $ "-}"-  if length ts == 0 && errorToFalse (p undefined)+  if length ts == 0 && p undefined == []   then putStrLn $ nm ++ "  =  error \"could not reify specification, suggestion: conjureFromSpec\"\n"   else do     putWithTimeSince t0 $ "pruning with " ++ show nRules ++ "/" ++ show nREs ++ " rules"@@ -261,17 +256,17 @@ -- The most important part of the result are the tiers of implementations -- however results also include candidates, tests and the underlying theory. conjpure :: Conjurable f => String -> f -> [Ingredient] -> Results-conjpure nm f  =  conjpure0 nm f (const True)+conjpure nm f  =  conjpure0 nm f (const [])  -- | Like 'conjureFromSpec' but in the pure world.  (cf. 'conjpure')-conjpureFromSpec :: Conjurable f => String -> (f -> Bool) -> [Ingredient] -> Results+conjpureFromSpec :: Conjurable f => String -> (f -> [Property]) -> [Ingredient] -> Results conjpureFromSpec nm p  =  conjpure0 nm undefined p  -- | This is where the actual implementation resides. -- The functions -- 'conjpure', 'conjpureFromSpec', 'conjure' and 'conjureFromSpec' -- all refer to this.-conjpure0 :: Conjurable f => String -> f -> (f -> Bool) -> [Ingredient] -> Results+conjpure0 :: Conjurable f => String -> f -> (f -> [Property]) -> [Ingredient] -> Results conjpure0 nm f p es  =  Results   { implementationss  =  implementationsT   , candidatess  =  candidatesT@@ -284,7 +279,7 @@   implementationsT  =  filterT implements candidatesT   implements fx  =  defnApparentlyTerminates fx                  && test fx-                 && errorToFalse (p (cevl maxRecursions fx))+                 && errorToFalse (testSpec maxTests $ p (cevl maxRecursions fx))   candidatesT  =  (if uniqueCandidates then nubCandidates maxTests maxRecursions nm f else id)                $  (if target > 0 then targetiers target else id)                $  (if maxSize > 0 then take maxSize else id)@@ -683,3 +678,17 @@  boolTy :: TypeRep boolTy  =  typ b_++-- TODO: move these property things to a module of their own?++-- | A test property provided as part of a specification for 'conjureFromSpec'.+--+-- Construct with 'property'.+type Property  =  [Bool]++-- | Provides a single test property to 'conjureFromSpec'.+property :: Testable a => a -> Property+property  =  map snd . results++testSpec :: Int -> [Property] -> Bool+testSpec maxTests  =  and . map (and . take maxTests)
src/Conjure/Ingredient.hs view
@@ -11,9 +11,8 @@ -- You are probably better off importing "Conjure". module Conjure.Ingredient   ( Ingredient-  , con-  , unfun   , fun+  , unfun   , iif   , ordcase   , guard@@ -26,6 +25,7 @@   , prim   , prif   , primOrdCaseFor+  , con   ) where @@ -36,12 +36,12 @@   -- | A single functional ingredient in conjuring.--- Specify conjure ingredients with 'con' and 'fun':+-- Specify conjure ingredients with 'unfun' and 'fun': ----- > conjure "foo" foo [ con False--- >                   , con True--- >                   , con (0 :: Int)--- >                   , con (1 :: Int)+-- > conjure "foo" foo [ unfun False+-- >                   , unfun True+-- >                   , unfun (0 :: Int)+-- >                   , unfun (1 :: Int) -- >                   , ... -- >                   , fun "&&" (&&) -- >                   , fun "||" (||)@@ -52,11 +52,10 @@ -- >                   ] -- -- Ingredients may include arbitrary--- constants ('con'),--- constructors ('con')--- or functions ('fun').+-- functional values ('fun')+-- and non-functional values ('unfun'). -- These may be built-in or user defined.--- Use 'con' on 'Show' instances+-- Use 'unfun' on 'Show' instances -- and 'fun' otherwise. -- -- This is internally@@ -66,23 +65,6 @@ type Ingredient  =  (Expr, Reification)  --- | Provides a constant or constructor as an ingredient to Conjure.---   To be used on 'Show' instances.---   (cf. 'fun')------ > conjure "foo" foo [ con False--- >                   , con True--- >                   , con (0 :: Int)--- >                   , con (1 :: Int)--- >                   , ...--- >                   ]------ Argument types have to be monomorphized,--- so use type bindings when applicable.-con :: (Conjurable a, Show a) => a -> Ingredient-con x  =  (val x, conjureType x)-- -- | Provided a 'Show'-able non-functional value to Conjure. --   (cf. 'fun') --@@ -95,12 +77,6 @@ -- -- Argument types have to be monomorphized, -- so use type bindings when applicable.------ TODO:  Make 'unfun' the standard way to create encode 'Show' values.------ This is a replacement to 'con'.--- In hindsight, 'con' is not such a great name:--- 'con'structors may be 'fun'ctional after all! unfun :: (Conjurable a, Show a) => a -> Ingredient unfun x  =  (val x, conjureType x) @@ -108,7 +84,7 @@ -- | Provides a functional value as an ingredient to Conjure. --   To be used on values that are not 'Show' instances --   such as functions.---   (cf. 'unfun', 'con')+--   (cf. 'unfun') -- -- > conjure "foo" foo [ ... -- >                   , fun "&&" (&&)@@ -136,7 +112,7 @@ -- > last' [x,y]  =  y -- > last' [x,y,z]  =  z ----- > > conjure "last" last' [ con ([] :: [Int])+-- > > conjure "last" last' [ unfun ([] :: [Int]) -- > >                      , fun ":" ((:) :: Int -> [Int] -> [Int]) -- > >                      , fun "null" (null :: [Int] -> Bool) -- > >                      , iif (undefined :: Int)@@ -166,7 +142,7 @@ -- > last' [x,y,z]  =  z -- -- > > conjure "last" last'--- > >   [ con ([] :: [Int])+-- > >   [ unfun ([] :: [Int]) -- > >   , fun ":" ((:) :: Int -> [Int] -> [Int]) -- > >   , fun "null" (null :: [Int] -> Bool) -- > >   , guard@@ -198,8 +174,8 @@ -- This should be used when one wants Conjure to consider ord-case expressions: -- -- > > conjure "mem" mem--- > >   [ con False--- > >   , con True+-- > >   [ unfun False+-- > >   , unfun True -- > >   , fun "`compare`" (compare :: Int -> Int -> Ordering) -- > >   , ordcase (undefined :: Bool) -- > >   ]@@ -279,10 +255,10 @@ {-# DEPRECATED Prim "'Prim' is deprecated, please use 'Ingredient' instead" #-}  --- | __DEPRECATED__.  Please use 'con' instead.+-- | __DEPRECATED__.  Please use 'unfun' instead. pr :: (Conjurable a, Show a) => a -> Ingredient pr  =  con-{-# DEPRECATED pr "'pr' is deprecated, please use 'con' instead" #-}+{-# DEPRECATED pr "'pr' is deprecated, please use 'unfun' instead" #-}  -- | __DEPRECATED__.  Please use 'fun' instead. prim :: Conjurable a => String -> a -> Ingredient@@ -296,3 +272,8 @@ primOrdCaseFor :: Conjurable a => a -> Ingredient primOrdCaseFor  =  ordcase {-# DEPRECATED primOrdCaseFor "'primOrdCaseFor' is deprecated, please use 'ordcase' instead" #-}++-- | __DEPRECATED__. Please use 'unfun' instead.+con :: (Conjurable a, Show a) => a -> Ingredient+con  =  unfun+{-# DEPRECATED con "'con' is deprecated, please use 'unfun' instead" #-}
test/factorial.hs view
@@ -13,8 +13,8 @@ main :: IO () main  =  do   conjure "factorial n" factorial-    [ con (0::Int)-    , con (1::Int)+    [ unfun (0::Int)+    , unfun (1::Int)     , fun "+" ((+) :: Int -> Int -> Int)     , fun "*" ((*) :: Int -> Int -> Int)     , fun "-" ((-) :: Int -> Int -> Int)