code-conjure 0.1.2 → 0.2.0
raw patch · 30 files changed
+596/−172 lines, 30 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Conjure: conjpure :: Conjurable f => String -> f -> [Expr] -> (Int, Int, [(Int, Expr)])
+ Conjure: conjpure :: Conjurable f => String -> f -> [Expr] -> ([[Expr]], [[Expr]], [Expr])
- Conjure: conjpureWith :: Conjurable f => Args -> String -> f -> [Expr] -> (Int, Int, [(Int, Expr)])
+ Conjure: conjpureWith :: Conjurable f => Args -> String -> f -> [Expr] -> ([[Expr]], [[Expr]], [Expr])
- Conjure.Engine: candidateExprs :: Conjurable f => String -> f -> Int -> Int -> (Expr -> Expr -> Bool) -> [[Expr]] -> [[Expr]]
+ Conjure.Engine: candidateExprs :: Conjurable f => String -> f -> Int -> Int -> (Expr -> Expr -> Bool) -> [Expr] -> [[Expr]]
- Conjure.Engine: conjpure :: Conjurable f => String -> f -> [Expr] -> (Int, Int, [(Int, Expr)])
+ Conjure.Engine: conjpure :: Conjurable f => String -> f -> [Expr] -> ([[Expr]], [[Expr]], [Expr])
- Conjure.Engine: conjpureWith :: Conjurable f => Args -> String -> f -> [Expr] -> (Int, Int, [(Int, Expr)])
+ Conjure.Engine: conjpureWith :: Conjurable f => Args -> String -> f -> [Expr] -> ([[Expr]], [[Expr]], [Expr])
Files
- .github/workflows/build.yml +10/−13
- .gitignore +1/−0
- Makefile +2/−0
- README.md +34/−25
- TODO.md +17/−4
- bench/runtime/zero/eg/arith.runtime +1/−1
- bench/runtime/zero/eg/bools.runtime +1/−1
- bench/runtime/zero/eg/factorial.runtime +1/−1
- bench/runtime/zero/eg/ints.runtime +1/−1
- bench/runtime/zero/eg/list.runtime +1/−0
- bench/runtime/zero/eg/tapps.runtime +1/−0
- bench/self.hs +6/−6
- code-conjure.cabal +11/−3
- eg/arith.hs +6/−6
- eg/bools.hs +9/−9
- eg/factorial.hs +60/−12
- eg/ints.hs +11/−11
- eg/list.hs +35/−3
- eg/tapps.hs +81/−0
- mk/depend.mk +10/−0
- src/Conjure.hs +7/−4
- src/Conjure/Engine.hs +56/−47
- src/Conjure/Expr.hs +1/−1
- test/model/bench/self.out +16/−5
- test/model/eg/arith.out +20/−4
- test/model/eg/bools.out +33/−5
- test/model/eg/factorial.out +20/−2
- test/model/eg/ints.out +43/−8
- test/model/eg/list.out +71/−0
- test/model/eg/tapps.out +30/−0
.github/workflows/build.yml view
@@ -30,8 +30,10 @@ - run: du -hd3 ~/.cabal ~/.ghc || true - run: haddock --version || sudo apt-get install ghc-haddock- - run: ghc --version- - run: cabal --version+ - run: ghc --version+ - run: cabal --version+ - run: haddock --version+ - run: ghc-pkg list - name: Check out repository uses: actions/checkout@v2@@ -86,8 +88,10 @@ - run: make --version || apt-get update - run: make --version || apt-get install make - - run: ghc --version- - run: cabal --version+ - run: ghc --version+ - run: cabal --version+ - run: haddock --version+ - run: ghc-pkg list - name: Check out repository uses: actions/checkout@v2@@ -117,15 +121,8 @@ key: v1-${{ runner.os }}-stack-${{ hashFiles('stack.yaml') }} restore-keys: v1-${{ runner.os }}-stack- - - name: Check out repository- uses: actions/checkout@v2- - run: make test-via-stack+ - run: stack --version - test-with-hugs:- runs-on: ubuntu-latest- needs: build-and-test- steps:- - run: sudo apt-get install hugs - name: Check out repository uses: actions/checkout@v2- - run: make hugs-test+ - run: make test-via-stack
.gitignore view
@@ -32,6 +32,7 @@ eg/factorial eg/ints eg/list+eg/tapps bench/self proto/u-conjure test/expr
Makefile view
@@ -10,6 +10,8 @@ eg/factorial \ eg/ints \ eg/bools \+ eg/list \+ eg/tapps \ bench/self \ proto/u-conjure
README.md view
@@ -46,22 +46,24 @@ and - background :: [Expr]- background =- [ val (0::Int)- , val (1::Int)- , value "+" ((+) :: Int -> Int -> Int)- , value "*" ((*) :: Int -> Int -> Int)- ]+ primitives :: [Expr]+ primitives = [ val (0::Int)+ , val (1::Int)+ , value "+" ((+) :: Int -> Int -> Int)+ , value "*" ((*) :: Int -> Int -> Int)+ ] running - > conjure "square" square background+ > conjure "square" square primitives yields square :: Int -> Int- -- looking through 815 candidates, 100% match, 3/3 assignments+ -- testing 3 combinations of argument values+ -- looking through 3 candidates of size 1+ -- looking through 3 candidates of size 2+ -- looking through 5 candidates of size 3 square x = x * x in less than a second.@@ -84,27 +86,34 @@ and - background :: [Expr]- background =- [ val (0::Int)- , val (1::Int)- , value "+" ((+) :: Int -> Int -> Int)- , value "*" ((*) :: Int -> Int -> Int)- , value "dec" (subtract 1 :: Int -> Int)- , value "isZero" ((==0) :: Int -> Bool)- , val False- , val True- ]+ primitives :: [Expr]+ primitives = [ val (0::Int)+ , val (1::Int)+ , value "+" ((+) :: Int -> Int -> Int)+ , value "*" ((*) :: Int -> Int -> Int)+ , value "dec" (subtract 1 :: Int -> Int)+ , value "==" ((==) :: Int -> Int -> Bool)+ ] running - > conjure "factorial" factorial background+ > conjure "factorial" factorial primitives yields factorial :: Int -> Int- -- looking through 8576 candidates, 100% match, 6/6 assignments- factorial x = if isZero x then 1 else x * factorial (dec x)+ -- testing 6 combinations of argument values+ -- looking through 3 candidates of size 1+ -- looking through 5 candidates of size 2+ -- looking through 8 candidates of size 3+ -- looking through 26 candidates of size 4+ -- looking through 59 candidates of size 5+ -- looking through 167 candidates of size 6+ -- looking through 581 candidates of size 7+ -- looking through 1654 candidates of size 8+ -- looking through 5754 candidates of size 9+ -- looking through 17797 candidates of size 10+ factorial n = if n == 0 then 1 else n * factorial (dec n) in about 3 seconds. @@ -112,9 +121,9 @@ It is also possible to generate: - factorial x = if x == 0 then 1 else x * factorial x - 1+ factorial n = if n == 0 then 1 else n * factorial (n - 1) -in about 30s by changing the background and increasing the size limit.+in about 90s by including `(-) :: Int -> Int -> Int` in the primitives. Related work
TODO.md view
@@ -3,11 +3,24 @@ A non-exhaustive list of things TO DO for Conjure. -* reduce to unique `candidateExprs` through testing.- We should only enumerate functions that were tested to be different.- We can limit the tests to the ones that are defined in the given function.+* report number of "hit" assignments, add ill example as a bench -* use partially defined implementations?+* refactor `candidateExprs` and `conjpureWith`.+ Move down conjuring of `(===)` from `conjpureWith` into `candidateExprs`.++* refactor `conjureTiersFor` to use `conjureMaybeTiersFor`++* implement `conjureHasTiers` and use it on `conjureMkEquation`;+ this will make it easy to backport unique candidateExprs from the erased+ commit back into the tool: just `discardLaterT (===)`.+ Will this impact performance a bit? I don't think so.+++### for later++* allow conjuring from tests instead of partial definitions?++* allow conjuring from partially defined implementations? partial :: ((Int -> Int) -> Int -> Int) -> (Int -> Int) partial impl = f
bench/runtime/zero/eg/arith.runtime view
@@ -1,1 +1,1 @@-4.55+0.82
bench/runtime/zero/eg/bools.runtime view
@@ -1,1 +1,1 @@-3.29+7.31
bench/runtime/zero/eg/factorial.runtime view
@@ -1,1 +1,1 @@-2.31+7.68
bench/runtime/zero/eg/ints.runtime view
@@ -1,1 +1,1 @@-1.95+2.42
+ bench/runtime/zero/eg/list.runtime view
@@ -0,0 +1,1 @@+8.59
+ bench/runtime/zero/eg/tapps.runtime view
@@ -0,0 +1,1 @@+1.24
bench/self.hs view
@@ -6,17 +6,17 @@ main :: IO () main = do- cj "?" ((+) :: Int -> Int -> Int) background- cj "?" ((*) :: Int -> Int -> Int) background- cj "i" ((+1) :: Int -> Int) background- cj "d" ((subtract 1) :: Int -> Int) background+ cj "?" ((+) :: Int -> Int -> Int) primitives+ cj "?" ((*) :: Int -> Int -> Int) primitives+ cj "i" ((+1) :: Int -> Int) primitives+ cj "d" ((subtract 1) :: Int -> Int) primitives where -- the monomorphism restriction strikes again cj :: Conjurable f => String -> f -> [Expr] -> IO () cj = conjureWith args{maxSize=3,maxEquationSize=0} -background :: [Expr]-background =+primitives :: [Expr]+primitives = [ val (0::Int) , val (1::Int) , value "+" ((+) :: Int -> Int -> Int)
code-conjure.cabal view
@@ -3,7 +3,7 @@ -- Copyright (C) 2021 Rudy Matela -- Distributed under the 3-Clause BSD licence (see the file LICENSE). name: code-conjure-version: 0.1.2+version: 0.2.0 synopsis: conjure Haskell functions out of partial definitions description: Conjure is a tool that produces Haskell functions out of partial definitions.@@ -47,7 +47,15 @@ , test/model/eg/*.out , test/model/proto/*.out , test/sdist-tested-with: GHC==8.10+tested-with: GHC==9.0+ , GHC==8.10+ , GHC==8.8+ , GHC==8.6+ , GHC==8.4+ , GHC==8.2+ , GHC==8.0+ , GHC==7.10+ , GHC==7.8 source-repository head type: git@@ -56,7 +64,7 @@ source-repository this type: git location: https://github.com/rudymatela/conjure- tag: v0.1.2+ tag: v0.2.0 library exposed-modules: Conjure
eg/arith.hs view
@@ -28,13 +28,13 @@ main :: IO () main = do- conjure "double" double background- conjure "add" add background- conjure "square" square background- conjure "tnpo" tnpo background+ conjure "double" double primitives+ conjure "add" add primitives+ conjure "square" square primitives+ conjure "tnpo" tnpo primitives -background :: [Expr]-background =+primitives :: [Expr]+primitives = [ val (0::Int) , val (1::Int) , value "+" ((+) :: Int -> Int -> Int)
eg/bools.hs view
@@ -16,15 +16,15 @@ main :: IO () main = do- conjure "and" (and' :: [Bool] -> Bool) background- conjure "or" (or' :: [Bool] -> Bool) background+ conjure "and" (and' :: [Bool] -> Bool) primitives+ conjure "or" (or' :: [Bool] -> Bool) primitives -- conjure can use fold as well- conjureWithMaxSize 4 "and" (and' :: [Bool] -> Bool) backgroundWithFold- conjureWithMaxSize 4 "or" (or' :: [Bool] -> Bool) backgroundWithFold+ conjure "and" (and' :: [Bool] -> Bool) primitivesWithFold+ conjure "or" (or' :: [Bool] -> Bool) primitivesWithFold -background :: [Expr]-background =+primitives :: [Expr]+primitives = [ value "not" not , value "||" (||) , value "&&" (&&)@@ -33,10 +33,10 @@ , value "tail" (tail :: [Bool] -> [Bool]) ] -backgroundWithFold :: [Expr]-backgroundWithFold =+primitivesWithFold :: [Expr]+primitivesWithFold = value "foldr" (foldr :: (Bool -> Bool -> Bool) -> Bool -> [Bool] -> Bool)- : background+ : primitives -- target (for and):
eg/factorial.hs view
@@ -14,19 +14,23 @@ main :: IO ()-main = conjure "factorial n" factorial background---background :: [Expr]-background =- [ val (0::Int)- , val (1::Int)- , value "+" ((+) :: Int -> Int -> Int)- , value "*" ((*) :: Int -> Int -> Int)- , value "dec" (subtract 1 :: Int -> Int)- , value "isZero" ((==0) :: Int -> Bool)- ]+main = do+ -- using enumFromTo+ conjure "factorial n" factorial+ [ val (1::Int)+ , value "enumFromTo" (enumFromTo :: Int -> Int -> [Int])+ , value "product" (product :: [Int] -> Int)+ ] + -- explicit recursion+ conjure "factorial n" factorial+ [ val (0::Int)+ , val (1::Int)+ , value "+" ((+) :: Int -> Int -> Int)+ , value "*" ((*) :: Int -> Int -> Int)+ , value "dec" (subtract 1 :: Int -> Int)+ , value "==" ((==) :: Int -> Int -> Bool)+ ] -- the actual factorial function: -- factorial n = if n == 0 then 1 else n * factorial (n - 1)@@ -41,3 +45,47 @@ -- -- factorial n = if (isZero n) then 1 else (n * factorial (dec n)) -- 1 2 3 4 5 6 7 8 9 symbols+++{-+-- Paramorphism of Naturals encoded as integers+para :: (Int -> b -> b) -> b -> Int -> b+para (?) z = p+ where+ p n | n < 0 = z -- no negatives for you :-)+ p 0 = z+ p n = n ? p (n-1)++The following works with a maxSize of 4, but not with a maxSize of 5.++ -- using a paramorphism+ conjure "factorial n" factorial+ [ val (1::Int)+ , value "para" (para :: (Int->Int->Int) -> Int -> Int -> Int)+ , value "*" ((*) :: Int -> Int -> Int)+ ]+++the factorial function is the following:++fact = para (*) 1+++now consider the following grow_fast function:++grow_fast = para (para (*)) 1 :: Integer -> Integer+++> growFast 1+1+> growFast 2+2+> growFast 3+6+> growFast 4+2880+> growFast 5+7148302174930174893017438921... 8000 digits!+> growFast 6+stack overflow+-}
eg/ints.hs view
@@ -25,16 +25,16 @@ main :: IO () main = do- conjure "second" (second :: [Int] -> Int) background- conjure "third" (third :: [Int] -> Int) background- conjure "sum" (sum' :: [Int] -> Int) background- conjure "product" (product' :: [Int] -> Int) background+ conjure "second" (second :: [Int] -> Int) primitives+ conjure "third" (third :: [Int] -> Int) primitives+ conjure "sum" (sum' :: [Int] -> Int) primitives+ conjure "product" (product' :: [Int] -> Int) primitives - conjureWithMaxSize 4 "sum" (sum' :: [Int] -> Int) backgroundWithFold- conjureWithMaxSize 4 "product" (product' :: [Int] -> Int) backgroundWithFold+ conjure "sum" (sum' :: [Int] -> Int) primitivesWithFold+ conjure "product" (product' :: [Int] -> Int) primitivesWithFold -background :: [Expr]-background =+primitives :: [Expr]+primitives = [ val (0 :: Int) , val (1 :: Int) , value "+" ((+) :: Int -> Int -> Int)@@ -44,10 +44,10 @@ , value "tail" (tail :: [Int] -> [Int]) ] -backgroundWithFold :: [Expr]-backgroundWithFold =+primitivesWithFold :: [Expr]+primitivesWithFold = value "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)- : background+ : primitives -- sum xs = if null xs then 0 else head xs + sum (tail xs) -- product xs = if null xs then 1 else head xs * product (tail xs)
eg/list.hs view
@@ -31,7 +31,7 @@ main = do -- length xs = if null xs then 0 else 1 + length (tail xs) -- 1 2 3 4 5 6 7 8 9- conjureWith args {maxSize = 9} "length" length'+ conjure "length" length' [ val (0 :: Int) , val (1 :: Int) , value "+" ((+) :: Int -> Int -> Int)@@ -41,7 +41,8 @@ -- reverse xs = if null xs then [] else reverse (tail xs) ++ [head xs] -- 1 2 3 4 5 6 7 8 9 10 11 12- conjureWith args {maxSize = 11} "reverse" reverse'+ -- needs size 11 with unit+ conjure "reverse" reverse' [ val ([] :: [Int]) , value "unit" ((:[]) :: Int -> [Int]) , value "++" ((++) :: [Int] -> [Int] -> [Int])@@ -52,10 +53,41 @@ -- sort xs = if null xs then [] else insert (head xs) (sort (tail xs)) -- 1 2 3 4 5 6 7 8 9 10- conjureWith args {maxSize = 10} "sort" sort'+ conjure "sort" sort' [ val ([] :: [Int]) , value "insert" (insert :: Int -> [Int] -> [Int]) , value "head" (head :: [Int] -> Int) , value "tail" (tail :: [Int] -> [Int]) , value "null" (null :: [Int] -> Bool)+ ]++ -- now through folds+ -- length xs = foldr (const (1 +)) 0 xs+ conjure "length" length'+ [ val (0 :: Int)+ , val (1 :: Int)+ , value "+" ((+) :: Int -> Int -> Int)+ , value "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)+ , value "const" (const :: (Int -> Int) -> Int -> (Int -> Int)) -- cheating?+ ]++ -- now through folds and some cheating+ -- reverse xs = foldr (\x xs -> xs ++ [x]) [] xs+ -- reverse xs = foldr (flip (++) . unit) [] xs+ conjure "reverse" reverse'+ [ val ([] :: [Int])+ , value "unit" ((:[]) :: Int -> [Int])+ , value "++" ((++) :: [Int] -> [Int] -> [Int])+ , value "foldr" (foldr :: (Int->[Int]->[Int]) -> [Int] -> [Int] -> [Int])+ -- these last two are cheats:+ , value "flip" (flip :: ([Int]->[Int]->[Int]) -> [Int] -> [Int] -> [Int])+ , value "." ((.) :: ([Int]->[Int]->[Int]) -> (Int->[Int]) -> Int -> [Int] -> [Int])+ ]++ -- now through folds+ -- sort xs = foldr insert [] xs+ conjure "sort" sort'+ [ val ([] :: [Int])+ , value "insert" (insert :: Int -> [Int] -> [Int])+ , value "foldr" (foldr :: (Int -> [Int] -> [Int]) -> [Int] -> [Int] -> [Int]) ]
+ eg/tapps.hs view
@@ -0,0 +1,81 @@+-- tapps.hs: conjure with (portable) type applications+--+-- Copyright (C) 2021 Rudy Matela+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).+{-# LANGUAGE CPP #-}+#if __GLASGOW_HASKELL__ < 800+#else+{-# LANGUAGE TypeApplications #-}+#endif++import Conjure++third :: [Int] -> Int+third [x,y,z] = z+third [x,y,z,w] = z++product' :: [Int] -> Int+product' [x] = x+product' [x,y] = x*y+product' [x,y,z] = x*y*z++main :: IO ()+main = do+ conjure "third" third primitives+ conjure "product" product' primitives+ conjure "product" product' primitivesWithFold++primitives :: [Expr]+primitives =+ [ val (0 :: Int)+ , val (1 :: Int)+#if __GLASGOW_HASKELL__ < 800+ , value "+" ((+) :: Int -> Int -> Int)+ , value "*" ((*) :: Int -> Int -> Int)+ , value "null" (null :: [Int] -> Bool)+ , value "head" (head :: [Int] -> Int)+ , value "tail" (tail :: [Int] -> [Int])+#else+ , value "+" ((+) @Int)+ , value "*" ((*) @Int)+-- the following #if was added just for dramatic effect (see notes below)+#if __GLASGOW_HASKELL__ < 710+ , value "null" (null @Int)+#else+ , value "null" (null @[] @Int)+#endif+ , value "head" (head @Int)+ , value "tail" (tail @Int)+#endif+ ]++primitivesWithFold :: [Expr]+#if __GLASGOW_HASKELL__ < 800+primitivesWithFold =+ value "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)+ : primitives+#else+-- the following #if was added just for dramatic effect (see notes below)+#if __GLASGOW_HASKELL__ < 710+primitivesWithFold = value "foldr" (foldr @Int @Int) : primitives+#else+primitivesWithFold = value "foldr" (foldr @[] @Int @Int) : primitives+#endif+#endif++-- Some notes:+--+-- From GHC 7.8 to GHC 7.10,+-- null, foldr and other functions were generalized+-- from lists to foldable containers.+-- The type application for the old version of null+-- is different than the one for the new version.+--+-- In the case of this file this is not really an issue+-- as the above change was introduced before TypeApplications even existed.+--+-- This illustrates that+-- we may have to use a different type application patterns+-- when using different versions of libraries.+-- In some cases, code using TypeApplications may be+-- less portable than it's full type binding counterparts.
mk/depend.mk view
@@ -58,6 +58,16 @@ src/Conjure/Engine.hs \ src/Conjure/Conjurable.hs \ eg/list.hs+eg/tapps: \+ eg/tapps.hs \+ mk/toplibs+eg/tapps.o: \+ src/Conjure/Utils.hs \+ src/Conjure.hs \+ src/Conjure/Expr.hs \+ src/Conjure/Engine.hs \+ src/Conjure/Conjurable.hs \+ eg/tapps.hs mk/All.o: \ src/Conjure/Utils.hs \ src/Conjure.hs \
src/Conjure.hs view
@@ -21,8 +21,8 @@ -- -- Step 2: declare a list with the potential building blocks: ----- > background :: [Expr]--- > background =+-- > primitives :: [Expr]+-- > primitives = -- > [ val (0::Int) -- > , val (1::Int) -- > , value "+" ((+) :: Int -> Int -> Int)@@ -31,9 +31,12 @@ -- -- Step 3: call conjure and see your generated function: ----- > > conjure "square" square background+-- > > conjure "square" square primitives -- > square :: Int -> Int--- > -- looking through 815 candidates, 100% match, 3/3 assignments+-- > -- testing 3 combinations of argument values+-- > -- looking through 3 candidates of size 1+-- > -- looking through 3 candidates of size 2+-- > -- looking through 5 candidates of size 3 -- > square x = x * x {-# LANGUAGE CPP #-} module Conjure
src/Conjure/Engine.hs view
@@ -58,7 +58,7 @@ args :: Args args = Args { maxTests = 60- , maxSize = 9+ , maxSize = 12 , maxRecursiveCalls = 1 , maxEquationSize = 5 , maxRecursionSize = 60@@ -66,51 +66,45 @@ -- | Like 'conjure' but in the pure world. ----- Returns a triple whose:------ 1. first element is the number of candidates considered------ 2. second element is the number of defined points in the given function+-- Returns a triple with: ----- 3. third element is a list of implementations encoded as 'Expr's--- paired with the number of matching points.-conjpure :: Conjurable f => String -> f -> [Expr] -> (Int,Int,[(Int,Expr)])+-- 1. tiers of implementations+-- 2. tiers of candidate bodies+-- 3. a list of tests+conjpure :: Conjurable f => String -> f -> [Expr] -> ([[Expr]], [[Expr]], [Expr]) conjpure = conjpureWith args -- | Like 'conjpure' but allows setting options through 'Args' and 'args'.-conjpureWith :: Conjurable f => Args -> String -> f -> [Expr] -> (Int,Int,[(Int,Expr)])-conjpureWith Args{..} nm f es = (length candidates,totalDefined,) $ sortBy compareResult- [ (ffxx .=. re, ffxx -==- e)- | e <- candidates- , apparentlyTerminates rrff e- , let re = recursexpr maxRecursionSize vffxx e- , ffxx ?=? re- ]+conjpureWith :: Conjurable f => Args -> String -> f -> [Expr] -> ([[Expr]], [[Expr]], [Expr])+conjpureWith Args{..} nm f es = (implementationsT, candidatesT, tests) where- totalDefined = ffxx .=. ffxx- candidates = filter (\e -> typ e == typ ffxx)- . concat- . take maxSize- $ candidateExprs nm f maxEquationSize maxRecursiveCalls (===)- [nub $ [val False, val True] ++ es ++ conjureIfs f]+ tests = [ffxx //- bs | bs <- dbss]+ implementationsT = mapT (vffxx -==-) $ filterT implements candidatesT+ implements e = apparentlyTerminates rrff e+ && ffxx ?=? recursexpr maxRecursionSize vffxx e+ candidatesT = filterT (\e -> typ e == typ ffxx)+ . take maxSize+ $ candidateExprs nm f maxEquationSize maxRecursiveCalls (===) es ffxx = canonicalApplication nm f vffxx = canonicalVarApplication nm f (rrff:_) = unfoldApp vffxx - (===), (?=?) :: Expr -> Expr -> Bool- e1 === e2 = isReallyTrue (e1 -==- e2)+ e1 === e2 = isReallyTrue (e1 -==- e2) e1 ?=? e2 = isTrueWhenDefined (e1 -==- e2)-- e1 .=. e2 = countTrue (e1 -==- e2) (-==-) = conjureMkEquation f - isTrueWhenDefined = all (errorToTrue . eval False) . gs- isReallyTrue = all (errorToFalse . eval False) . gs- countTrue = count (errorToFalse . eval False) . gs+ isTrueWhenDefined e = all (errorToFalse . eval False) $ map (e //-) dbss+ isReallyTrue = all (errorToFalse . eval False) . gs gs :: Expr -> [Expr] gs = take maxTests . grounds (conjureTiersFor f) + bss, dbss :: [[(Expr,Expr)]]+ bss = take maxTests $ groundBinds (conjureTiersFor f) ffxx+ dbss = [bs | bs <- bss, errorToFalse . eval False $ e //- bs]+ where+ e = ffxx -==- ffxx+ -- | Conjures an implementation of a partially defined function. -- -- Takes a 'String' with the name of a function,@@ -124,8 +118,8 @@ -- > square 1 = 1 -- > square 2 = 4 -- >--- > background :: [Expr]--- > background =+-- > primitives :: [Expr]+-- > primitives = -- > [ val (0::Int) -- > , val (1::Int) -- > , value "+" ((+) :: Int -> Int -> Int)@@ -134,12 +128,15 @@ -- -- The conjure function does the following: ----- > > conjure "square" square background+-- > > conjure "square" square primitives -- > square :: Int -> Int--- > -- looking through 815 candidates, 100% match, 3/3 assignments+-- > -- testing 3 combinations of argument values+-- > -- looking through 3 candidates of size 1+-- > -- looking through 3 candidates of size 2+-- > -- looking through 5 candidates of size 3 -- > square x = x * x ----- The background is defined with 'val' and 'value'.+-- The primitives list is defined with 'val' and 'value'. conjure :: Conjurable f => String -> f -> [Expr] -> IO () conjure = conjureWith args @@ -159,17 +156,18 @@ conjureWith :: Conjurable f => Args -> String -> f -> [Expr] -> IO () conjureWith args nm f es = do print (var (head $ words nm) f)- putStr $ "-- looking through " ++ show ncs ++ " candidates"- hFlush stdout- case rs of- [] -> putStrLn $ "\ncannot conjure"- ((n,e):_) -> do putStrLn $ ", " ++ showMatch n- putStrLn $ showEq e--- nes -> putStrLn . unlines $ "":[showEq e ++ " -- " ++ show n | (n,e) <- nes]- putStrLn ""+ putStrLn $ "-- testing " ++ show (length ts) ++ " combinations of argument values"+ pr 1 rs where- (ncs,t,rs) = conjpureWith args nm f es- showMatch n = show (n % t) ++ "% match, " ++ show n ++ "/" ++ show t ++ " assignments"+ pr n [] = putStrLn $ "cannot conjure"+ pr n ((is,es):rs) = do+ putStrLn $ "-- looking through " ++ show (length es) ++ " candidates of size " ++ show n+ case is of+ [] -> pr (n+1) rs+ (i:_) -> do putStrLn $ showEq i+ putStrLn ""+ rs = zip iss css+ (iss, css, ts) = conjpureWith args nm f es showEq eq = showExpr (lhs eq) ++ " = " ++ showExpr (rhs eq) candidateExprs :: Conjurable f@@ -177,9 +175,20 @@ -> Int -> Int -> (Expr -> Expr -> Bool)- -> [[Expr]]+ -> [Expr] -> [[Expr]]-candidateExprs nm f sz mc (===) ess = expressionsT $ [ef:exs] \/ ess+candidateExprs nm f sz mc (===) es =+ candidateExprsT nm f sz mc (===)+ [nub $ [val False, val True] ++ es ++ conjureIfs f]++candidateExprsT :: Conjurable f+ => String -> f+ -> Int+ -> Int+ -> (Expr -> Expr -> Bool)+ -> [[Expr]]+ -> [[Expr]]+candidateExprsT nm f sz mc (===) ess = expressionsT $ [ef:exs] \/ ess where (ef:exs) = unfoldApp $ canonicalVarApplication nm f thy = theoryFromAtoms (===) sz $ [conjureHoles f] \/ ess
src/Conjure/Expr.hs view
@@ -168,7 +168,7 @@ -- > > ifFor (undefined :: String) -- > if :: Bool -> [Char] -> [Char] -> [Char] ----- You need to provide this as part of your building blocks on the background+-- You need to provide this as part of your building blocks on the primitives -- if you want recursive functions to be considered and produced. ifFor :: Typeable a => a -> Expr ifFor a = value "if" (\p x y -> if p then x else y `asTypeOf` a)
test/model/bench/self.out view
@@ -1,16 +1,27 @@ (?) :: Int -> Int -> Int--- looking through 52 candidates, 100% match, 60/60 assignments+-- testing 60 combinations of argument values+-- looking through 4 candidates of size 1+-- looking through 0 candidates of size 2+-- looking through 48 candidates of size 3 x ? y = x + y (?) :: Int -> Int -> Int--- looking through 52 candidates, 100% match, 60/60 assignments+-- testing 60 combinations of argument values+-- looking through 4 candidates of size 1+-- looking through 0 candidates of size 2+-- looking through 48 candidates of size 3 x ? y = x * y i :: Int -> Int--- looking through 24 candidates, 100% match, 60/60 assignments+-- testing 60 combinations of argument values+-- looking through 3 candidates of size 1+-- looking through 3 candidates of size 2+-- looking through 18 candidates of size 3 i x = x + 1 d :: Int -> Int--- looking through 24 candidates+-- testing 60 combinations of argument values+-- looking through 3 candidates of size 1+-- looking through 3 candidates of size 2+-- looking through 18 candidates of size 3 cannot conjure-
test/model/eg/arith.out view
@@ -1,16 +1,32 @@ double :: Int -> Int--- looking through 815 candidates, 100% match, 4/4 assignments+-- testing 4 combinations of argument values+-- looking through 3 candidates of size 1+-- looking through 3 candidates of size 2+-- looking through 5 candidates of size 3 double x = x + x add :: Int -> Int -> Int--- looking through 28024 candidates, 100% match, 4/4 assignments+-- testing 4 combinations of argument values+-- looking through 4 candidates of size 1+-- looking through 0 candidates of size 2+-- looking through 29 candidates of size 3 add x y = x + y square :: Int -> Int--- looking through 815 candidates, 100% match, 3/3 assignments+-- testing 3 combinations of argument values+-- looking through 3 candidates of size 1+-- looking through 3 candidates of size 2+-- looking through 5 candidates of size 3 square x = x * x tnpo :: Int -> Int--- looking through 815 candidates, 100% match, 3/3 assignments+-- testing 3 combinations of argument values+-- looking through 3 candidates of size 1+-- looking through 3 candidates of size 2+-- looking through 5 candidates of size 3+-- looking through 20 candidates of size 4+-- looking through 13 candidates of size 5+-- looking through 97 candidates of size 6+-- looking through 42 candidates of size 7 tnpo x = x + (x + (x + 1))
test/model/eg/bools.out view
@@ -1,16 +1,44 @@ and :: [Bool] -> Bool--- looking through 1207 candidates, 100% match, 14/14 assignments+-- testing 14 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 3 candidates of size 2+-- looking through 6 candidates of size 3+-- looking through 6 candidates of size 4+-- looking through 16 candidates of size 5+-- looking through 41 candidates of size 6+-- looking through 103 candidates of size 7+-- looking through 278 candidates of size 8+-- looking through 752 candidates of size 9 and ps = null ps || head ps && and (tail ps) or :: [Bool] -> Bool--- looking through 1207 candidates, 78% match, 11/14 assignments-or ps = head ps || or (tail ps)+-- testing 14 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 3 candidates of size 2+-- looking through 6 candidates of size 3+-- looking through 6 candidates of size 4+-- looking through 16 candidates of size 5+-- looking through 41 candidates of size 6+-- looking through 103 candidates of size 7+-- looking through 278 candidates of size 8+-- looking through 752 candidates of size 9+-- looking through 1963 candidates of size 10+-- looking through 5427 candidates of size 11+or ps = not (null ps || not (head ps || or (tail ps))) and :: [Bool] -> Bool--- looking through 19 candidates, 100% match, 14/14 assignments+-- testing 14 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 3 candidates of size 2+-- looking through 6 candidates of size 3+-- looking through 8 candidates of size 4 and ps = foldr (&&) True ps or :: [Bool] -> Bool--- looking through 19 candidates, 100% match, 14/14 assignments+-- testing 14 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 3 candidates of size 2+-- looking through 6 candidates of size 3+-- looking through 8 candidates of size 4 or ps = foldr (||) False ps
test/model/eg/factorial.out view
@@ -1,4 +1,22 @@ factorial :: Int -> Int--- looking through 8576 candidates, 100% match, 6/6 assignments-factorial n = if isZero n then 1 else n * factorial (dec n)+-- testing 6 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 2 candidates of size 2+-- looking through 0 candidates of size 3+-- looking through 2 candidates of size 4+factorial n = product (enumFromTo 1 n)++factorial :: Int -> Int+-- testing 6 combinations of argument values+-- looking through 3 candidates of size 1+-- looking through 5 candidates of size 2+-- looking through 8 candidates of size 3+-- looking through 26 candidates of size 4+-- looking through 59 candidates of size 5+-- looking through 167 candidates of size 6+-- looking through 581 candidates of size 7+-- looking through 1654 candidates of size 8+-- looking through 5754 candidates of size 9+-- looking through 17797 candidates of size 10+factorial n = if n == 0 then 1 else n * factorial (dec n)
test/model/eg/ints.out view
@@ -1,24 +1,59 @@ second :: [Int] -> Int--- looking through 636 candidates, 100% match, 47/47 assignments+-- testing 47 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 2 candidates of size 2+-- looking through 3 candidates of size 3 second xs = head (tail xs) third :: [Int] -> Int--- looking through 636 candidates, 100% match, 34/34 assignments+-- testing 34 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 2 candidates of size 2+-- looking through 3 candidates of size 3+-- looking through 5 candidates of size 4 third xs = head (tail (tail xs)) sum :: [Int] -> Int--- looking through 636 candidates, 13% match, 5/37 assignments-sum xs = if null (tail xs) then head xs else sum xs+-- testing 37 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 2 candidates of size 2+-- looking through 3 candidates of size 3+-- looking through 5 candidates of size 4+-- looking through 13 candidates of size 5+-- looking through 26 candidates of size 6+-- looking through 63 candidates of size 7+-- looking through 154 candidates of size 8+-- looking through 368 candidates of size 9+-- looking through 902 candidates of size 10+sum xs = if null xs then 0 else head xs + sum (tail xs) product :: [Int] -> Int--- looking through 636 candidates, 13% match, 5/37 assignments-product xs = if null (tail xs) then head xs else product xs+-- testing 37 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 2 candidates of size 2+-- looking through 3 candidates of size 3+-- looking through 5 candidates of size 4+-- looking through 13 candidates of size 5+-- looking through 26 candidates of size 6+-- looking through 63 candidates of size 7+-- looking through 154 candidates of size 8+-- looking through 368 candidates of size 9+-- looking through 902 candidates of size 10+product xs = if null xs then 1 else head xs * product (tail xs) sum :: [Int] -> Int--- looking through 15 candidates, 100% match, 37/37 assignments+-- testing 37 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 2 candidates of size 2+-- looking through 3 candidates of size 3+-- looking through 8 candidates of size 4 sum xs = foldr (+) 0 xs product :: [Int] -> Int--- looking through 15 candidates, 100% match, 37/37 assignments+-- testing 37 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 2 candidates of size 2+-- looking through 3 candidates of size 3+-- looking through 8 candidates of size 4 product xs = foldr (*) 1 xs
+ test/model/eg/list.out view
@@ -0,0 +1,71 @@+length :: [Int] -> Int+-- testing 38 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 1 candidates of size 2+-- looking through 2 candidates of size 3+-- looking through 3 candidates of size 4+-- looking through 5 candidates of size 5+-- looking through 11 candidates of size 6+-- looking through 22 candidates of size 7+-- looking through 53 candidates of size 8+-- looking through 101 candidates of size 9+length xs = if null xs then 0 else 1 + length (tail xs)++reverse :: [Int] -> [Int]+-- testing 38 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 4 candidates of size 2+-- looking through 9 candidates of size 3+-- looking through 24 candidates of size 4+-- looking through 65 candidates of size 5+-- looking through 215 candidates of size 6+-- looking through 673 candidates of size 7+-- looking through 2178 candidates of size 8+-- looking through 7154 candidates of size 9+-- looking through 23801 candidates of size 10+-- looking through 80160 candidates of size 11+reverse xs = if null xs then xs else reverse (tail xs) ++ unit (head xs)++sort :: [Int] -> [Int]+-- testing 30 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 4 candidates of size 2+-- looking through 6 candidates of size 3+-- looking through 12 candidates of size 4+-- looking through 31 candidates of size 5+-- looking through 98 candidates of size 6+-- looking through 287 candidates of size 7+-- looking through 792 candidates of size 8+-- looking through 2220 candidates of size 9+-- looking through 6516 candidates of size 10+sort xs = if null xs then xs else insert (head xs) (sort (tail xs))++length :: [Int] -> Int+-- testing 38 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 1 candidates of size 2+-- looking through 1 candidates of size 3+-- looking through 4 candidates of size 4+-- looking through 4 candidates of size 5+-- looking through 27 candidates of size 6+length xs = foldr (const (1 +)) 0 xs++reverse :: [Int] -> [Int]+-- testing 38 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 2 candidates of size 2+-- looking through 1 candidates of size 3+-- looking through 5 candidates of size 4+-- looking through 1 candidates of size 5+-- looking through 25 candidates of size 6+-- looking through 77 candidates of size 7+reverse xs = foldr (flip (++) . unit) [] xs++sort :: [Int] -> [Int]+-- testing 30 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 2 candidates of size 2+-- looking through 0 candidates of size 3+-- looking through 2 candidates of size 4+sort xs = foldr insert [] xs+
+ test/model/eg/tapps.out view
@@ -0,0 +1,30 @@+third :: [Int] -> Int+-- testing 34 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 2 candidates of size 2+-- looking through 3 candidates of size 3+-- looking through 5 candidates of size 4+third xs = head (tail (tail xs))++product :: [Int] -> Int+-- testing 37 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 2 candidates of size 2+-- looking through 3 candidates of size 3+-- looking through 5 candidates of size 4+-- looking through 13 candidates of size 5+-- looking through 26 candidates of size 6+-- looking through 63 candidates of size 7+-- looking through 154 candidates of size 8+-- looking through 368 candidates of size 9+-- looking through 902 candidates of size 10+product xs = if null xs then 1 else head xs * product (tail xs)++product :: [Int] -> Int+-- testing 37 combinations of argument values+-- looking through 2 candidates of size 1+-- looking through 2 candidates of size 2+-- looking through 3 candidates of size 3+-- looking through 8 candidates of size 4+product xs = foldr (*) 1 xs+