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 +58/−156
- bench/candidates.hs +10/−10
- bench/carry-on.hs +2/−2
- bench/erroneous.hs +10/−10
- bench/gps.hs +92/−84
- bench/gps2.hs +86/−74
- bench/ill-hit.hs +11/−9
- bench/p12.hs +3/−3
- bench/p30.hs +5/−5
- bench/redundants.hs +10/−10
- bench/runtime/zero/eg/dupos.runtime +1/−1
- bench/runtime/zero/eg/ints.runtime +1/−1
- bench/runtime/zero/eg/list.runtime +1/−1
- bench/runtime/zero/eg/setelem.runtime +1/−1
- bench/self.hs +2/−2
- bench/strategies.hs +2/−2
- bench/terpret.hs +10/−10
- bench/unique.hs +9/−9
- bench/weird.hs +2/−2
- changelog.md +7/−0
- code-conjure.cabal +2/−2
- eg/arith.hs +2/−2
- eg/bits.hs +5/−5
- eg/bools.hs +2/−2
- eg/bst.hs +17/−17
- eg/colin/IntFuns.hs +4/−4
- eg/colin/ListFuns.hs +14/−14
- eg/count.hs +4/−4
- eg/dupos.hs +10/−14
- eg/dupos.txt +6/−8
- eg/either.hs +9/−9
- eg/factorial.hs +4/−4
- eg/fib01.hs +2/−2
- eg/fibonacci.hs +3/−3
- eg/gcd.hs +1/−1
- eg/higher.hs +38/−26
- eg/ints.hs +21/−20
- eg/ints.txt +4/−4
- eg/list.hs +14/−14
- eg/list.txt +2/−2
- eg/maybe.hs +10/−10
- eg/oddeven.hs +8/−8
- eg/peano.hs +2/−2
- eg/pow.hs +4/−4
- eg/replicate.hs +4/−4
- eg/setelem.hs +4/−8
- eg/setelem.txt +1/−1
- eg/sort.hs +5/−5
- eg/spec.hs +27/−21
- eg/subset.hs +3/−3
- eg/take-drop.hs +6/−6
- eg/tapps.hs +2/−2
- eg/these.hs +6/−6
- eg/tree.hs +11/−11
- eg/tri.hs +1/−1
- eg/tuple.hs +9/−13
- mk/depend.mk +6/−1
- src/Conjure.hs +9/−7
- src/Conjure/Engine.hs +37/−28
- src/Conjure/Ingredient.hs +22/−41
- test/factorial.hs +2/−2
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)