diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -86,3 +86,4 @@
 test/defn
 test/derive
 test/red
+test/factorial
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -8,10 +8,6 @@
   $(shell grep -q "Arch Linux" /etc/lsb-release && echo -dynamic)
 # -Wall -Werror -Wno-unused-matches -Wno-orphans -Wno-name-shadowing -Wno-incomplete-uni-patterns -Wno-unused-pattern-binds
 HADDOCKFLAGS = \
-  -i $(shell find ~/.cabal -name leancheck.haddock | tail -1) \
-  -i $(shell find ~/.cabal -name express.haddock   | tail -1) \
-  -i $(shell find ~/.cabal -name speculate.haddock | tail -1) \
-  -i $(shell find /usr/share/doc/ghc*/html/libraries -name template-haskell.haddock | tail -1) \
   $(shell grep -q "Arch Linux" /etc/lsb-release && echo --optghc=-dynamic) \
   | grep -v "^Warning: Couldn't find .haddock for export [A-Z]$$"
 INSTALL_DEPS = leancheck express speculate template-haskell
@@ -69,6 +65,7 @@
   proto/u-conjure
 
 TESTS = \
+  test/factorial \
   test/expr \
   test/defn \
   test/conjurable \
@@ -86,8 +83,8 @@
 
 ghci: src/Conjure.ghci
 
-tags: src test/Test.hs
-	hasktags $^
+tags: src
+	ctags -R src
 
 # Disclaimer: This bench target is not intended to generate paper-grade runtime
 #             datapoints as it runs each benchmark just once.  This target is
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -57,22 +57,22 @@
 	factorial 3  =  6
 	factorial 4  =  24
 
-Next, declare a list of primitives that seem like interesting pieces
+Next, declare a list of ingredients that seem like interesting pieces
 in the final fully-defined implementation.
 For example,
-here is a list of primitives including
+here is a list of ingredients including
 addition, multiplication, subtraction and their neutral elements:
 
-	primitives :: [Prim]
-	primitives  =  [ pr (0::Int)
-	               , pr (1::Int)
-	               , prim "+" ((+) :: Int -> Int -> Int)
-	               , prim "*" ((*) :: Int -> Int -> Int)
-	               , prim "-" ((-) :: Int -> Int -> Int)
-	               ]
+	ingredients :: [Ingredient]
+	ingredients  =  [ con (0::Int)
+	                , con (1::Int)
+	                , fun "+" ((+) :: Int -> Int -> Int)
+	                , fun "*" ((*) :: Int -> Int -> Int)
+	                , fun "-" ((-) :: Int -> Int -> Int)
+	                ]
 
 Finally, call the [`conjure`] function,
-passing the function name, the partial definition and the list of primitives:
+passing the function name, the partial definition and the list of ingredients:
 
 	factorial :: Int -> Int
 	-- 0.1s, testing 4 combinations of argument values
@@ -121,11 +121,11 @@
 given list constructors, zero, one and subtraction:
 
 	> conjure "take" (take' :: Int -> [A] -> [A])
-	>   [ pr (0 :: Int)
-	>   , pr (1 :: Int)
-	>   , pr ([] :: [A])
-	>   , prim ":" ((:) :: A -> [A] -> [A])
-	>   , prim "-" ((-) :: Int -> Int -> Int)
+	>   [ con (0 :: Int)
+	>   , con (1 :: Int)
+	>   , con ([] :: [A])
+	>   , fun ":" ((:) :: A -> [A] -> [A])
+	>   , fun "-" ((-) :: Int -> Int -> Int)
 	>   ]
 	take :: Int -> [A] -> [A]
 	-- 0.2s, testing 153 combinations of argument values
@@ -138,9 +138,9 @@
 	take x (y:xs)  =  y:take (x - 1) xs
 
 The above example also takes less than a second to run in a modern laptop.
-The selection of functions in the list of primitives was minimized
+The selection of functions in the list of ingredients was minimized
 to what was absolutely needed here.
-With a larger collection as primitives YMMV.
+With a larger collection as ingredients YMMV.
 
 
 Synthesizing from specifications (for advanced users)
@@ -161,16 +161,16 @@
 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 primitives:
+Let's start with the ingredients:
 
-	primitives :: [Prim]
-	primitives  =  [ pr ([] :: [Int])
-	               , prim "not" not
-	               , prim "&&" (&&)
-	               , prim ":" ((:) :: Int -> [Int] -> [Int])
-	               , prim "elem" (elem :: Int -> [Int] -> Bool)
-	               , prif (undefined :: [Int])
-	               ]
+	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:
 
@@ -183,7 +183,7 @@
 
 Here is what [`conjure`] prints:
 
-	> conjure "duplicates" duplicates primitives
+	> conjure "duplicates" duplicates ingredients
 	duplicates :: [Int] -> [Int]
 	-- testing 1 combinations of argument values
 	-- pruning with 21/26 rules
@@ -206,7 +206,7 @@
 
 Here is what [`conjure`] now prints:
 
-	> conjure "duplicates" duplicates primitives
+	> conjure "duplicates" duplicates ingredients
 	duplicates :: [Int] -> [Int]
 	-- testing 3 combinations of argument values
 	-- pruning with 21/26 rules
@@ -246,7 +246,7 @@
 
 Now Conjure prints a correct implementation:
 
-	> conjure "duplicates" duplicates primitives
+	> conjure "duplicates" duplicates ingredients
 	duplicates :: [Int] -> [Int]
 	-- 0.2s, testing 6 combinations of argument values
 	-- 0.3s, pruning with 21/26 rules
@@ -283,7 +283,7 @@
 Now, we can use the function [`conjureFromSpecWith`] to generate the same duplicates function
 passing our `duplicatesSpec` as argument:
 
-	> conjureFromSpecWith args{maxSize=18} "duplicates" duplicatesSpec primitives
+	> 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
diff --git a/TODO.md b/TODO.md
--- a/TODO.md
+++ b/TODO.md
@@ -3,37 +3,26 @@
 
 A non-exhaustive list of things TO DO for Conjure.
 
-* Warn when there are no tests!
-  Test this on high order functions.
-  Encode `error "could not reify specification"`
-
-* change cannot conjure to "search exhausted",
-  to indicate that Conjure has _shown_ that
-  there is no way to build the given function
-  with the given ingredients up to the given size.
-
-* Expand tests on `conjurableOK`?
-
-* Add `test/conjure.hs` with some basic conjuring...
+* Make so that derived Listable instances `reset`
+  constructors that are not recursive.
+  This change will need to be done in LeanCheck itself.
 
-* Fix bug with pairwise in eg/tuple
+* Detail two new proposed pruning rules from Colin.
+  (email from Feb 24 and follow-up in meeting)
 
 * Allow timeout setting?
 
 * Rethink Conjurable typeclass?
 
-* Rename primitives to ingredients?
-
 * Allow chains of guards (see below).
 
-* Move `Args` into `[Prim]`?
-
 * Better error reporting when `Listable` is out-of-scope when using `deriveConjurable`.
   This needs to be implemented on LeanCheck itself.
 
 * forbid recursion into negatives (see below)
 
-* Warn when no tests are present somehow?
+* Add way to consider functions that don't increase size of arguments in recursive calls
+	(qsort example)
 
 
 ## Allow chains of guards
diff --git a/bench/candidates.hs b/bench/candidates.hs
--- a/bench/candidates.hs
+++ b/bench/candidates.hs
@@ -7,7 +7,7 @@
 import Conjure.Defn
 import Data.Express.Fixtures
 
-printCandidates :: Conjurable f => Int -> Int -> String -> f -> [Prim] -> IO ()
+printCandidates :: Conjurable f => Int -> Int -> String -> f -> [Ingredient] -> IO ()
 printCandidates m n nm f ps  =  do
   putStrLn $ "Candidates for: " ++ nm ++ " :: " ++ show (typeOf f)
   putStrLn $ "  pruning with " ++ show nRules ++ "/" ++ show nREs ++ " rules"
@@ -32,54 +32,54 @@
   csC  =  concat cssC
   css1  =  take m css1'
   cssC  =  take m cssC'
-  (css1', thy, _, _)  =  candidateDefns1 args nm f ps
-  (cssC', _, pss, ds)  =  candidateDefnsC args nm f ps
+  (css1', thy, _, _)  =  candidateDefns nm f (singlePattern : ps)
+  (cssC', _, pss, ds)  =  candidateDefns nm f ps
   nRules  =  length (rules thy)
   nREs  =  length (equations thy) + nRules
 
 main :: IO ()
 main  =  do
   printCandidates 9 6 "foo" (undefined :: Int -> Int)
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
     ]
 
   printCandidates 9 5 "?" (undefined :: Int -> Int -> Int)
-    [ pr (0 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "dec" (subtract 1 :: Int -> Int)
+    [ con (0 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "dec" (subtract 1 :: Int -> Int)
     ]
 
   printCandidates 9 6 "goo" (undefined :: [Int] -> [Int])
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
     ]
 
   printCandidates 9 6 "??" (undefined :: [Int] -> [Int] -> [Int])
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
     ]
 
   printCandidates 9 6 "ton" (undefined :: Bool -> Bool)
-    [ pr False
-    , pr True
-    , prim "&&" (&&)
-    , prim "||" (||)
-    , prim "not" not
+    [ con False
+    , con True
+    , fun "&&" (&&)
+    , fun "||" (||)
+    , fun "not" not
     ]
 
   printCandidates 9 6 "&|" (undefined :: Bool -> Bool -> Bool)
-    [ pr False
-    , pr True
-    , prim "&&" (&&)
-    , prim "||" (||)
-    , prim "not" not
+    [ con False
+    , con True
+    , fun "&&" (&&)
+    , fun "||" (||)
+    , fun "not" not
     ]
 
   -- Degenerate case:
@@ -88,6 +88,6 @@
   -- nevertheless useful for observing candidate filtering
   -- through other means
   printCandidates 9 6 "gcd" (undefined :: Int -> Int -> Int)
-    [ pr (0::Int)
-    , prim "`mod`" (mod :: Int -> Int -> Int)
+    [ con (0::Int)
+    , fun "`mod`" (mod :: Int -> Int -> Int)
     ]
diff --git a/bench/carry-on.hs b/bench/carry-on.hs
--- a/bench/carry-on.hs
+++ b/bench/carry-on.hs
@@ -14,12 +14,14 @@
 main :: IO ()
 main  =  do
   -- carry on Conjuring larger implementations
-  conjureWith args{carryOn = True, maxSize = 11} "factorial n" factorial
-    [ pr (0::Int)
-    , pr (1::Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
+  conjure "factorial n" factorial
+    [ con (0::Int)
+    , con (1::Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
+    , carryOn
+    , maxSize 11
     ]
   -- should produce:
   -- factorial 0  =  1
diff --git a/bench/carry-on.txt b/bench/carry-on.txt
--- a/bench/carry-on.txt
+++ b/bench/carry-on.txt
@@ -43,5 +43,5 @@
 factorial x  =  (0 - x) * (0 - factorial (x - 1))
 
 -- tested 10001 candidates
-cannot conjure
+factorial n  =  undefined  -- search exhausted
 
diff --git a/bench/erroneous.hs b/bench/erroneous.hs
--- a/bench/erroneous.hs
+++ b/bench/erroneous.hs
@@ -22,8 +22,8 @@
 -- * maximum candidate size (5 = few seconds, 7 = few minutes);
 -- * function name (for pretty-printing purposes);
 -- * proxy value to indicate the type of functions to generate;
--- * list of primitives, in Conjure-compatible form.
-printErroneousCandidates :: Conjurable f => Int -> String -> f -> [Prim] -> IO ()
+-- * list of ingredients, in Conjure-compatible form.
+printErroneousCandidates :: Conjurable f => Int -> String -> f -> [Ingredient] -> IO ()
 printErroneousCandidates n nm f ps  =  do
   putStrLn $ "Erroneous candidates for: " ++ nm ++ " :: " ++ show (typeOf f)
   putStrLn $ "  pruning with " ++ show nRules ++ "/" ++ show nREs ++ " rules"
@@ -40,7 +40,7 @@
   css            =  take n
                  .  discardT isRedundantByIntroduction -- additional pruning rule
                  $  css'
-  (css', thy, _, _) =  candidateDefnsC args nm f ps  -- Conjure uses this for listing candidates
+  (css', thy, _, _) =  candidateDefns nm f ps  -- Conjure uses this for listing candidates
   nRules         =  length (rules thy)
   nREs           =  length (equations thy) + nRules
   maxTests       =  60 -- a hardcoded value probably will not hurt in this simple benchmark
@@ -58,45 +58,45 @@
   let n = 6
 
   printErroneousCandidates (n+1) "foo" (undefined :: Int -> Int)
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , pr (2 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , con (2 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
     ]
 
   printErroneousCandidates n "?" (undefined :: Int -> Int -> Int)
-    [ pr (0 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "dec" (subtract 1 :: Int -> Int)
+    [ con (0 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "dec" (subtract 1 :: Int -> Int)
     ]
 
   printErroneousCandidates (n+1) "goo" (undefined :: [Int] -> [Int])
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
     ]
 
   printErroneousCandidates n "??" (undefined :: [Int] -> [Int] -> [Int])
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
     ]
 
   printErroneousCandidates n "ton" (undefined :: Bool -> Bool)
-    [ pr False
-    , pr True
-    , prim "&&" (&&)
-    , prim "||" (||)
-    , prim "not" not
+    [ con False
+    , con True
+    , fun "&&" (&&)
+    , fun "||" (||)
+    , fun "not" not
     ]
 
   printErroneousCandidates n "&|" (undefined :: Bool -> Bool -> Bool)
-    [ pr False
-    , pr True
-    , prim "&&" (&&)
-    , prim "||" (||)
-    , prim "not" not
+    [ con False
+    , con True
+    , fun "&&" (&&)
+    , fun "||" (||)
+    , fun "not" not
     ]
diff --git a/bench/gps.hs b/bench/gps.hs
--- a/bench/gps.hs
+++ b/bench/gps.hs
@@ -38,44 +38,44 @@
 
 gps1c :: IO ()
 gps1c  =  conjure "gps1" gps1p
-  [ prim "+" ((+) :: Float -> Float -> Float)
-  , prim "fromIntegral" (fromIntegral :: Int -> Float)
+  [ fun "+" ((+) :: Float -> Float -> Float)
+  , fun "fromIntegral" (fromIntegral :: Int -> Float)
   ]
 
 gps1c30p :: IO ()
 gps1c30p  =  conjure "gps1" gps1p
-  [ pr (0 :: Float)
-  , pr (1 :: Float)
-  , pr (1/2 :: Float)
-  , pr (-1 :: Float)
-  , prim "+" ((+) :: Float -> Float -> Float)
-  , prim "*" ((*) :: Float -> Float -> Float)
-  , prim "-" ((-) :: Float -> Float -> Float)
-  , prim "abs" (abs :: Float -> Float)
-  , prim "negate" (negate :: Float -> Float)
-  , prim "id" (id :: Float -> Float)
-  , prim "fromIntegral" (fromIntegral :: Int -> Float)
+  [ con (0 :: Float)
+  , con (1 :: Float)
+  , con (1/2 :: Float)
+  , con (-1 :: Float)
+  , fun "+" ((+) :: Float -> Float -> Float)
+  , fun "*" ((*) :: Float -> Float -> Float)
+  , fun "-" ((-) :: Float -> Float -> Float)
+  , fun "abs" (abs :: Float -> Float)
+  , fun "negate" (negate :: Float -> Float)
+  , fun "id" (id :: Float -> Float)
+  , fun "fromIntegral" (fromIntegral :: Int -> Float)
 
-  , pr (0 :: Int)
-  , pr (1 :: Int)
-  , pr (-1 :: Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "*" ((*) :: Int -> Int -> Int)
-  , prim "-" ((-) :: Int -> Int -> Int)
-  , prim "div" (div :: Int -> Int -> Int)
-  , prim "mod" (mod :: Int -> Int -> Int)
-  , prim "^" ((^) :: Int -> Int -> Int)
-  , prim "abs" (abs :: Int -> Int)
-  , prim "negate" (negate :: Int -> Int)
-  , prim "id" (id :: Int -> Int)
-  , prim "round" (round :: Float -> Int)
-  , prim "truncate" (truncate :: Float -> Int)
+  , con (0 :: Int)
+  , con (1 :: Int)
+  , con (-1 :: Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "*" ((*) :: Int -> Int -> Int)
+  , fun "-" ((-) :: Int -> Int -> Int)
+  , fun "div" (div :: Int -> Int -> Int)
+  , fun "mod" (mod :: Int -> Int -> Int)
+  , fun "^" ((^) :: Int -> Int -> Int)
+  , fun "abs" (abs :: Int -> Int)
+  , fun "negate" (negate :: Int -> Int)
+  , fun "id" (id :: Int -> Int)
+  , fun "round" (round :: Float -> Int)
+  , fun "truncate" (truncate :: Float -> Int)
 
-  , pr False
-  , pr True
-  , prim "&&" (&&)
-  , prim "||" (||)
-  , prim "not" not
+  , con False
+  , con True
+  , fun "&&" (&&)
+  , fun "||" (||)
+  , fun "not" not
   ]
 
 
@@ -94,16 +94,18 @@
   | otherwise  =  Nothing
 
 gps2c :: IO ()
-gps2c  =  conjureWith args{maxTests=5040, maxSize=30} "gps2" gps2p
-  [ pr "small"
-  , pr "large"
-  , pr (1000 :: Int)
-  , pr (2000 :: Int)
-  , prim "Just" (Just :: String -> Maybe String)
-  , prim "Nothing" (Nothing :: Maybe String)
-  , prim "<=" ((<=) :: Int -> Int -> Bool)
-  , prim "<" ((<) :: Int -> Int -> Bool)
-  , prif (undefined :: Maybe String)
+gps2c  =  conjure "gps2" gps2p
+  [ con "small"
+  , con "large"
+  , con (1000 :: Int)
+  , con (2000 :: Int)
+  , fun "Just" (Just :: String -> Maybe String)
+  , fun "Nothing" (Nothing :: Maybe String)
+  , fun "<=" ((<=) :: Int -> Int -> Bool)
+  , fun "<" ((<) :: Int -> Int -> Bool)
+  , iif (undefined :: Maybe String)
+  , maxTests 5040
+  , maxSize 30
   ]
 
 
@@ -122,19 +124,20 @@
 gps3c :: IO ()
 gps3c  =  do
   conjure "gps3" gps3p
-    [ pr (1 :: Int)
-    , prim "enumFromThenTo" ((\x y z -> take 720 $ enumFromThenTo x y z) :: Int -> Int -> Int -> [Int])
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
+    [ con (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)
     ]
 
   -- not possible, no recursive descent
-  conjureWith args{maxSize=8} "gps3" gps3p
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "<" ((<) :: Int -> Int -> Bool)
-    , prif (undefined :: [Int])
+  conjure "gps3" gps3p
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "<" ((<) :: Int -> Int -> Bool)
+    , iif (undefined :: [Int])
+    , maxSize 8
     ]
 
 
@@ -155,9 +158,9 @@
 gps4c :: IO ()
 gps4c  =  do
   conjure "gps4" gps4p
-    [ prim "length" (length :: String -> Int)
-    , prim "<" ((<) :: Int -> Int -> Bool)
-    , prim "&&" (&&)
+    [ fun "length" (length :: String -> Int)
+    , fun "<" ((<) :: Int -> Int -> Bool)
+    , fun "&&" (&&)
     ]
 
 
@@ -176,13 +179,14 @@
   | otherwise   =  c:gps5g cs
 
 gps5c :: IO ()
-gps5c  =  conjureWith args{maxSize=6} "gps5" gps5p -- can't find
-  [ pr ""
-  , prim ":" ((:) :: Char -> String -> String)
-  , pr '!'
-  , prim "==" ((==) :: Char -> Char -> Bool)
-  , prim "isLetter" (isLetter :: Char -> Bool)
-  , prif (undefined :: String -> String)
+gps5c  =  conjure "gps5" gps5p -- can't find
+  [ con ""
+  , fun ":" ((:) :: Char -> String -> String)
+  , con '!'
+  , fun "==" ((==) :: Char -> Char -> Bool)
+  , fun "isLetter" (isLetter :: Char -> Bool)
+  , iif (undefined :: String -> String)
+  , maxSize 6
   ]
 
 
@@ -213,15 +217,17 @@
 -- Removing three or setting maxEqSize to 4 makes it unhang.
 -- But a size of 15 or 17 is simplyl out of our reach.
 gps6c :: IO ()
-gps6c  =  conjureWith args{maxSize=6,maxEquationSize=3} "gps6" gps6p
-  [ pr (1 :: Int)
-  , pr (2 :: Int)
-  , pr (3 :: Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "*" ((*) :: Int -> Int -> Int)
-  , prim "`div`" (div :: Int -> Int -> Int)
-  , prim "even" (even :: Int -> Bool)
-  , prif (undefined :: Int)
+gps6c  =  conjure "gps6" gps6p
+  [ con (1 :: Int)
+  , con (2 :: Int)
+  , con (3 :: Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "*" ((*) :: Int -> Int -> Int)
+  , fun "`div`" (div :: Int -> Int -> Int)
+  , fun "even" (even :: Int -> Bool)
+  , iif (undefined :: Int)
+  , maxSize 6
+  , maxEquationSize 3
   ]
 
 
@@ -238,15 +244,15 @@
 
 gps7c :: IO ()
 gps7c  =  conjure "gps7" gps7p
-  [ prim "," ((,) :: String -> Int -> (String, Int))
-  , prim "init" (init :: String -> String)
-  , prim "unlines" unlines
-  , prim "words" words
-  , prim "length" (length :: String -> Int)
-  , prim "filter" (filter :: (Char -> Bool) -> String -> String)
-  , prim "not" not
-  , prim "." ((.) :: (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool) -- cheat?
-  , prim "isSpace" (isSpace :: Char -> Bool)
+  [ fun "," ((,) :: String -> Int -> (String, Int))
+  , fun "init" (init :: String -> String)
+  , fun "unlines" unlines
+  , fun "words" words
+  , fun "length" (length :: String -> Int)
+  , fun "filter" (filter :: (Char -> Bool) -> String -> String)
+  , fun "not" not
+  , fun "." ((.) :: (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool) -- cheat?
+  , fun "isSpace" (isSpace :: Char -> Bool)
   ]
 
 
@@ -294,14 +300,15 @@
   sq  =  (^2)
 
 gps9c :: IO ()
-gps9c  =  conjureWith args{maxTests=60} "gps9" gps9p
-  [ pr (1 :: Int)
-  , prim "map" (map :: (Int -> Int) -> [Int] -> [Int])
-  , prim "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])
-  , prim ".." (enumFromTo :: Int -> Int -> [Int])
-  , prim ">" ((>) :: Int -> Int -> Bool)
-  , prim "even" (even :: Int -> Bool)
-  , prim "sq" ((^2) :: Int -> Int)  -- invented separately
+gps9c  =  conjure "gps9" gps9p
+  [ con (1 :: Int)
+  , fun "map" (map :: (Int -> Int) -> [Int] -> [Int])
+  , fun "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])
+  , fun ".." (enumFromTo :: Int -> Int -> [Int])
+  , fun ">" ((>) :: Int -> Int -> Bool)
+  , fun "even" (even :: Int -> Bool)
+  , fun "sq" ((^2) :: Int -> Int)  -- invented separately
+  , maxTests 60
   ]
 
 
@@ -346,35 +353,35 @@
 gps10c :: IO ()
 gps10c  =  do
   conjure "wallisNext" wallisNextP
-    [ pr (1 :: Integer)
-    , pr (2 :: Integer)
-    , prim "+" ((+) :: Integer -> Integer -> Integer)
-    , prim "*" ((*) :: Integer -> Integer -> Integer)
-    , prim "%" ((%) :: Integer -> Integer -> Rational)
-    , prim "<" ((<) :: Integer -> Integer -> Bool)
---  , prim "numerator" (numerator :: Rational -> Integer)
---  , prim "denominator" (denominator :: Rational -> Integer)
-    , prif (undefined :: Rational)
+    [ con (1 :: Integer)
+    , con (2 :: Integer)
+    , fun "+" ((+) :: Integer -> Integer -> Integer)
+    , fun "*" ((*) :: Integer -> Integer -> Integer)
+    , fun "%" ((%) :: Integer -> Integer -> Rational)
+    , fun "<" ((<) :: Integer -> Integer -> Bool)
+--  , fun "numerator" (numerator :: Rational -> Integer)
+--  , fun "denominator" (denominator :: Rational -> Integer)
+    , iif (undefined :: Rational)
     ]
 
   -- simplified background
   conjure "wallisNext" wallisNextP
-    [ pr (0 :: Integer)
-    , pr (1 :: Integer)
-    , prim "+" ((+) :: Integer -> Integer -> Integer)
-    , prim "*" ((*) :: Integer -> Integer -> Integer)
-    , prim "%" ((%) :: Integer -> Integer -> Rational)
+    [ con (0 :: Integer)
+    , con (1 :: Integer)
+    , fun "+" ((+) :: Integer -> Integer -> Integer)
+    , fun "*" ((*) :: Integer -> Integer -> Integer)
+    , fun "%" ((%) :: Integer -> Integer -> Rational)
     ]
 
   conjure "gps10" gps10p
-    [ pr (2 :: Integer)
-    , pr (3 :: Integer)
-    , prim "%" ((%) :: Integer -> Integer -> Rational)
---  , pr (2/3 :: Rational)
-    , prim "product"    (product :: [Rational] -> Rational)
-    , prim "take"       (take :: Int -> [Rational] -> [Rational])
-    , prim "iterate"    ((\f -> take 720 . iterate f) :: (Rational -> Rational) -> Rational -> [Rational])
-    , prim "wallisNext" wallisNext
+    [ con (2 :: Integer)
+    , con (3 :: Integer)
+    , fun "%" ((%) :: Integer -> Integer -> Rational)
+--  , con (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])
+    , fun "wallisNext" wallisNext
     ]
 
 
@@ -396,16 +403,16 @@
 gps11c :: IO ()
 gps11c  =  do
   conjure "gps11" gps11p
-    [ prim "reverse" (reverse :: [Int] -> [Int])
-    , prim "length"  (length :: String -> Int)
-    , prim "map"     (map :: (String -> Int) -> [String] -> [Int])
+    [ fun "reverse" (reverse :: [Int] -> [Int])
+    , fun "length"  (length :: String -> Int)
+    , fun "map"     (map :: (String -> Int) -> [String] -> [Int])
     ]
 
   conjure "gps11" gps11p
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
-    , prim "length"  (length :: String -> Int)
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
+    , fun "length"  (length :: String -> Int)
     ]
 
 
@@ -424,15 +431,16 @@
 
 gps12c :: IO ()
 gps12c  =  do
-  conjureWith args{maxSize = 11} "gps12" gps12p
-    [ prim "length"    (length :: [Int] -> Int)
-    , prim "reverse"   (reverse :: [Int] -> [Int])
-    , prim "findIndex" (findIndex :: (Int -> Bool) -> [Int] -> Maybe Int)
-    , prim "fromJust"  (fromJust :: Maybe Int -> Int)
-    , prim "-"         ((-) :: Int -> Int -> Int)
-    , prim "=="        ((==) :: Int -> Int -> Bool)
-    , pr (0 :: Int)
-    , pr (1 :: Int)
+  conjure "gps12" gps12p
+    [ fun "length"    (length :: [Int] -> Int)
+    , fun "reverse"   (reverse :: [Int] -> [Int])
+    , fun "findIndex" (findIndex :: (Int -> Bool) -> [Int] -> Maybe Int)
+    , fun "fromJust"  (fromJust :: Maybe Int -> Int)
+    , fun "-"         ((-) :: Int -> Int -> Int)
+    , fun "=="        ((==) :: Int -> Int -> Bool)
+    , con (0 :: Int)
+    , con (1 :: Int)
+    , maxSize 11
     ]
 
 
@@ -450,12 +458,12 @@
 gps13c :: IO ()
 gps13c  =  do
   conjure "gps13" gps13p
-    [ prim "0" (0 :: Rational)
-    , prim "+" ((+) :: Rational -> Rational -> Rational)
-    , prim "/" ((/) :: Rational -> Rational -> Rational)
-    , prim "foldr" (foldr :: (Rational -> Rational -> Rational) -> Rational -> [Rational] -> Rational)
-    , prim "length" (length :: [Rational] -> Int)
-    , prim "fromIntegral" (fromIntegral :: Int -> Rational)
+    [ fun "0" (0 :: Rational)
+    , fun "+" ((+) :: Rational -> Rational -> Rational)
+    , fun "/" ((/) :: Rational -> Rational -> Rational)
+    , fun "foldr" (foldr :: (Rational -> Rational -> Rational) -> Rational -> [Rational] -> Rational)
+    , fun "length" (length :: [Rational] -> Int)
+    , fun "fromIntegral" (fromIntegral :: Int -> Rational)
     ]
 
 
@@ -488,30 +496,30 @@
 gps14c :: IO ()
 gps14c  =  do
   conjure "odd" odd'
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , pr (2 :: Int)
-    , prim "`mod`" (mod :: Int -> Int -> Int)
-    , prim "/=" ((/=) :: Int -> Int -> Bool)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , con (2 :: Int)
+    , fun "`mod`" (mod :: Int -> Int -> Int)
+    , fun "/=" ((/=) :: Int -> Int -> Bool)
     ]
 
   conjure "gps14" gps14p
-    [ prim "odd" (odd :: Int -> Bool)
-    , prim "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])
-    , prim "length" (length :: [Int] -> Int)
+    [ fun "odd" (odd :: Int -> Bool)
+    , fun "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])
+    , fun "length" (length :: [Int] -> Int)
     ]
 
   -- hah!  I was expecting Conjure to use an if like above, but it was smarter:
   -- gps14 []  =  0
   -- gps14 (x:xs)  =  x `mod` 2 + gps14 xs
   conjure "gps14" gps14p
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , pr (2 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "`mod`" (mod :: Int -> Int -> Int)
-    , prim "==" ((==) :: Int -> Int -> Bool)
-    , prif (undefined :: Int)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , con (2 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "`mod`" (mod :: Int -> Int -> Int)
+    , fun "==" ((==) :: Int -> Int -> Bool)
+    , iif (undefined :: Int)
     ]
 
 
@@ -530,8 +538,8 @@
 gps15c :: IO ()
 gps15c  =  do
   conjure "gps15" gps15p
-    [ prim "==" ((==) :: [Int] -> [Int] -> Bool)
-    , prim "reverse" (reverse :: [Int] -> [Int])
+    [ fun "==" ((==) :: [Int] -> [Int] -> Bool)
+    , fun "reverse" (reverse :: [Int] -> [Int])
     ]
 
 
@@ -551,8 +559,8 @@
 gps16c :: IO ()
 gps16c  =  do
   conjure "gps16" gps16p
-    [ prim "`isSubsequenceOf`" (isSubsequenceOf :: String -> String -> Bool)
-    , prim "sort" (sort :: String -> String)
+    [ fun "`isSubsequenceOf`" (isSubsequenceOf :: String -> String -> Bool)
+    , fun "sort" (sort :: String -> String)
     ]
 
 
@@ -569,11 +577,11 @@
 
 gps17c :: IO ()
 gps17c  =  conjure "gps17" gps17p
-  [ pr (0 :: Int)
-  , pr (1 :: Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "*" ((*) :: Int -> Int -> Int)
-  , prim "-" ((-) :: Int -> Int -> Int)
+  [ con (0 :: Int)
+  , con (1 :: Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "*" ((*) :: Int -> Int -> Int)
+  , fun "-" ((-) :: Int -> Int -> Int)
   ]
 
 
@@ -594,14 +602,14 @@
 gps18c :: IO ()
 gps18c  =  do
   conjure "gps18" gps18p
-    [ pr ([] :: [Int])
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
     ]
 
   conjure "gps18" gps18p
-    [ prim "+" ((+) :: Int -> Int -> Int)
-    , prim "zipWith" (zipWith :: (Int -> Int -> Int) -> [Int] -> [Int] -> [Int])
+    [ fun "+" ((+) :: Int -> Int -> Int)
+    , fun "zipWith" (zipWith :: (Int -> Int -> Int) -> [Int] -> [Int] -> [Int])
     ]
 
 
@@ -623,12 +631,12 @@
 gps19c  =  do
   -- speculate takes too long
   conjure "gps19" gps19p $ take 0
-    [ prim "words" (words :: String -> [String])
---  , prim "words" (lines :: String -> [String])
-    , prim "unwords" (unwords :: [String] -> String)
-    , prim "unlines" (unlines :: [String] -> String)
---  , prim "chunk" (chunk :: Int -> [String] -> [[String]])
---  , prim "map" (map :: ([String] -> String) -> [[String]] -> [String])
+    [ fun "words" (words :: String -> [String])
+--  , fun "words" (lines :: String -> [String])
+    , fun "unwords" (unwords :: [String] -> String)
+    , fun "unlines" (unlines :: [String] -> String)
+--  , fun "chunk" (chunk :: Int -> [String] -> [[String]])
+--  , fun "map" (map :: ([String] -> String) -> [[String]] -> [String])
     ]
 
 
@@ -680,29 +688,30 @@
 gps20c :: IO ()
 gps20c  =  do
   conjure "isVowel" isVowel'
-    [ pr 'a'
-    , pr 'e'
-    , pr 'i'
-    , pr 'o'
-    , pr 'u'
-    , pr 'y'
-    , pr True
-    , pr False
+    [ con 'a'
+    , con 'e'
+    , con 'i'
+    , con 'o'
+    , con 'u'
+    , con 'y'
+    , con True
+    , con False
     ]
 
-  conjureFromSpecWith args{target=50400} "pig1" pig1Spec
-    [ pr "ay"
-    , prif (undefined :: String)
-    , prim "isVowel" isVowel
-    , prim "++" ((++) :: String -> String -> String)
-    , prim ":" ((:) :: Char -> String -> String)
+  conjureFromSpec "pig1" pig1Spec
+    [ con "ay"
+    , iif (undefined :: String)
+    , fun "isVowel" isVowel
+    , fun "++" ((++) :: String -> String -> String)
+    , fun ":" ((:) :: Char -> String -> String)
+    , target 50400
     ]
 
   conjureFromSpec "gps20c" gps20s
-    [ prim "words" (words :: String -> [String])
-    , prim "unwords" (unwords :: [String] -> String)
-    , prim "map" (map :: (String -> String) -> [String] -> [String])
-    , prim "pig1" pig1
+    [ fun "words" (words :: String -> [String])
+    , fun "unwords" (unwords :: [String] -> String)
+    , fun "map" (map :: (String -> String) -> [String] -> [String])
+    , fun "pig1" pig1
     ]
 
 
@@ -721,11 +730,11 @@
 
 gps21c :: IO ()
 gps21c  =  conjure "gps21" gps21p
-  [ pr ([] :: [Int])
-  , pr (0 :: Int)
-  , prim ":" ((:) :: Int -> [Int] -> [Int])
-  , prim "<" ((<) :: Int -> Int -> Bool)
-  , prif (undefined :: Int)
+  [ con ([] :: [Int])
+  , con (0 :: Int)
+  , fun ":" ((:) :: Int -> [Int] -> [Int])
+  , fun "<" ((<) :: Int -> Int -> Bool)
+  , iif (undefined :: Int)
   ]
 
 
@@ -764,10 +773,10 @@
 gps22c :: IO ()
 gps22c  =  do
   conjureFromSpec "gps22" gps22s
-    [ pr (0 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "map" (map :: (Int -> Int) -> [Int] -> [Int])
-    , prim "scrabble1" scrabble1
+    [ con (0 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "map" (map :: (Int -> Int) -> [Int] -> [Int])
+    , fun "scrabble1" scrabble1
     ]
 
 
@@ -793,14 +802,14 @@
 
 gps24c :: IO ()
 gps24c  =  conjure "gps24" gps24p
-  [ pr ' '
-  , pr (64 :: Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "`mod`" (mod :: Int -> Int -> Int)
-  , prim "sum" (sum :: [Int] -> Int)
-  , prim "ord" ord
-  , prim "chr" chr
-  , prim "map" (map :: (Char -> Int) -> String -> [Int])
+  [ con ' '
+  , con (64 :: Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "`mod`" (mod :: Int -> Int -> Int)
+  , fun "sum" (sum :: [Int] -> Int)
+  , fun "ord" ord
+  , fun "chr" chr
+  , fun "map" (map :: (Char -> Int) -> String -> [Int])
   ]
 
 
@@ -820,15 +829,15 @@
 -- out of reach performance-wise
 gps25c :: IO ()
 gps25c  =  conjure "gps25" gps25p $ take 0
-  [ pr (0 :: Int)
-  , pr (10 :: Int)
-  , pr ([] :: [Int])
-  , prim ":" ((:) :: Int -> [Int] -> [Int])
-  , prif (undefined :: [Int])
-  , prim "abs" (abs :: Int -> Int)
-  , prim "<" ((<) :: Int -> Int -> Bool)
-  , prim "rem" (rem :: Int -> Int -> Int)
-  , prim "quot" (quot :: Int -> Int -> Int)
+  [ con (0 :: Int)
+  , con (10 :: Int)
+  , con ([] :: [Int])
+  , fun ":" ((:) :: Int -> [Int] -> [Int])
+  , iif (undefined :: [Int])
+  , fun "abs" (abs :: Int -> Int)
+  , fun "<" ((<) :: Int -> Int -> Bool)
+  , fun "rem" (rem :: Int -> Int -> Int)
+  , fun "quot" (quot :: Int -> Int -> Int)
   ]
 
 
@@ -851,14 +860,15 @@
 
 -- out of reach performance-wise
 gps26c :: IO ()
-gps26c  =  conjureWith args{maxSize=2} "gps26" gps26p
-  [ pr 'A'
-  , pr 'B'
-  , pr 'C'
-  , pr 'D'
-  , pr 'F'
-  , prif (undefined :: Char)
-  , prim ">=" ((>=) :: Int -> Int -> Bool)
+gps26c  =  conjure "gps26" gps26p
+  [ con 'A'
+  , con 'B'
+  , con 'C'
+  , con 'D'
+  , con 'F'
+  , iif (undefined :: Char)
+  , fun ">=" ((>=) :: Int -> Int -> Bool)
+  , maxSize 2
   ]
 
 
@@ -878,14 +888,14 @@
 gps27c :: IO ()
 gps27c  =  do
   conjure "gps27" gps27p
-    [ prim "<" ((<) :: Int -> Int -> Bool)
-    , prim "&&" (&&)
-    , prif (undefined :: Int)
+    [ fun "<" ((<) :: Int -> Int -> Bool)
+    , fun "&&" (&&)
+    , iif (undefined :: Int)
     ]
 
   conjure "gps27b" gps27p
-    [ prim "min" (min :: Int -> Int -> Int)
-    , prim "max" (max :: Int -> Int -> Int)
+    [ fun "min" (min :: Int -> Int -> Int)
+    , fun "max" (max :: Int -> Int -> Int)
     ]
 
 
@@ -899,7 +909,7 @@
 
 gps28c :: IO ()
 gps28c  =  conjure "gps28" gps28p
-  [ prim "`min`" (min :: Int -> Int -> Int)
+  [ fun "`min`" (min :: Int -> Int -> Int)
   ]
 
 
@@ -920,11 +930,11 @@
 
 gps29c :: IO ()
 gps29c  =  conjureFromSpec "gps29" gps29s
-  [ pr (0 :: Int)
-  , pr (1 :: Int)
-  , prim "+" ((+) :: Int->Int->Int)
-  , prif (undefined :: Int)
-  , prim "isVowel" isVowel
+  [ con (0 :: Int)
+  , con (1 :: Int)
+  , fun "+" ((+) :: Int->Int->Int)
+  , iif (undefined :: Int)
+  , fun "isVowel" isVowel
   ]
 
 
diff --git a/bench/gps.txt b/bench/gps.txt
--- a/bench/gps.txt
+++ b/bench/gps.txt
@@ -55,7 +55,7 @@
 -- 81 candidates of size 7
 -- 36 candidates of size 8
 -- tested 136 candidates
-cannot conjure
+gps3  =  undefined  -- search exhausted
 
 gps4 :: [Char] -> [Char] -> [Char] -> Bool
 -- testing 9 combinations of argument values
@@ -84,7 +84,7 @@
 -- 4 candidates of size 5
 -- 0 candidates of size 6
 -- tested 8 candidates
-cannot conjure
+gps5  =  undefined  -- search exhausted
 
 gps6 :: Int -> Int
 -- testing 9 combinations of argument values
@@ -96,7 +96,7 @@
 -- 186 candidates of size 5
 -- 165 candidates of size 6
 -- tested 385 candidates
-cannot conjure
+gps6  =  undefined  -- search exhausted
 
 gps7 :: [Char] -> ([Char],Int)
 -- testing 4 combinations of argument values
@@ -123,7 +123,7 @@
 -- 0 candidates of size 3
 -- 0 candidates of size 4
 -- tested 0 candidates
-cannot conjure
+gps8  =  undefined  -- search exhausted
 
 gps9 :: Int -> [Int]
 -- testing 3 combinations of argument values
@@ -309,7 +309,7 @@
 -- 1048 candidates of size 9
 -- tested 466 candidates
 gps17 0  =  0
-gps17 x  =  gps17 (x - 1) + x * x
+gps17 x  =  x * x + gps17 (x - 1)
 
 gps18 :: [Int] -> [Int] -> [Int]
 -- testing 3 combinations of argument values
@@ -344,7 +344,7 @@
 -- 1 candidates of size 1
 -- 0 candidates of size 2
 -- tested 1 candidates
-cannot conjure
+gps19  =  undefined  -- search exhausted
 
 isVowel :: Char -> Bool
 -- testing 12 combinations of argument values
@@ -439,14 +439,10 @@
 -- 3 candidates of size 6
 -- tested 4 candidates
 gps22 ""  =  0
-gps22 (c:cs)  =  gps22 cs + scrabble1 c
+gps22 (c:cs)  =  scrabble1 c + gps22 cs
 
 gps23 :: [Char] -> ([(Int,Int)],Int,Double)
--- pruning with 0/0 rules
--- 0 candidates of size 1
--- 0 candidates of size 2
--- tested 0 candidates
-cannot conjure
+gps23  =  error "could not reify specification, suggestion: conjureFromSpec"
 
 gps24 :: [Char] -> Char
 -- testing 4 combinations of argument values
@@ -469,7 +465,7 @@
 -- pruning with 0/0 rules
 -- 0 candidates of size 1
 -- tested 0 candidates
-cannot conjure
+gps25  =  undefined  -- search exhausted
 
 gps26 :: Int -> Int -> Int -> Int -> Int -> Char
 -- testing 5 combinations of argument values
@@ -477,7 +473,7 @@
 -- 5 candidates of size 1
 -- 0 candidates of size 2
 -- tested 5 candidates
-cannot conjure
+gps26  =  undefined  -- search exhausted
 
 gps27 :: Int -> Int -> Int -> Int
 -- testing 3 combinations of argument values
@@ -535,5 +531,5 @@
 -- 24 candidates of size 9
 -- tested 36 candidates
 gps29 ""  =  0
-gps29 (c:cs)  =  gps29 cs + (if isVowel c then 1 else 0)
+gps29 (c:cs)  =  (if isVowel c then 1 else 0) + gps29 cs
 
diff --git a/bench/gps2.hs b/bench/gps2.hs
--- a/bench/gps2.hs
+++ b/bench/gps2.hs
@@ -42,36 +42,38 @@
 gps1c :: IO ()
 gps1c  =  do
   conjure "gps1" gps1p
-    [ pr (0 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim ">" ((>) :: Int -> Int -> Bool)
-    , prim "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
-    , prim "sum" (sum :: [Int] -> Int)
-    , prim "findIndex" (findIndex :: (Int -> Bool) -> [Int] -> Maybe Int)
-    , prim "map" (map :: ([Int] -> Int) -> [[Int]] -> [Int])
-    , prim "inits" (inits :: [Int] -> [[Int]])
-    , prim "tail" (tail :: [[Int]] -> [[Int]])
+    [ con (0 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun ">" ((>) :: Int -> Int -> Bool)
+    , fun "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
+    , fun "sum" (sum :: [Int] -> Int)
+    , fun "findIndex" (findIndex :: (Int -> Bool) -> [Int] -> Maybe Int)
+    , fun "map" (map :: ([Int] -> Int) -> [[Int]] -> [Int])
+    , fun "inits" (inits :: [Int] -> [[Int]])
+    , fun "tail" (tail :: [[Int]] -> [[Int]])
     ]
 
   conjure "gps1" gps1p
-    [ pr (0 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim ">" ((>) :: Int -> Int -> Bool)
-    , prim "sum" (sum :: [Int] -> Int)
-    , prim "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
-    , prim "findIndex" (findIndex :: (Int -> Bool) -> [Int] -> Maybe Int)
-    , prim "map" (map :: ([Int] -> Int) -> [[Int]] -> [Int])
-    , prim "inits" (inits :: [Int] -> [[Int]])
-    , prim "tail" (tail :: [[Int]] -> [[Int]])
+    [ con (0 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun ">" ((>) :: Int -> Int -> Bool)
+    , fun "sum" (sum :: [Int] -> Int)
+    , fun "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
+    , fun "findIndex" (findIndex :: (Int -> Bool) -> [Int] -> Maybe Int)
+    , fun "map" (map :: ([Int] -> Int) -> [[Int]] -> [Int])
+    , fun "inits" (inits :: [Int] -> [[Int]])
+    , fun "tail" (tail :: [[Int]] -> [[Int]])
     ]
 
-  conjureWithMaxSize 4 "gps1" gps1p2
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "<" ((<) :: Int -> Int -> Bool)
-    , prif (undefined :: Int)
-    , prim "undefined" (undefined :: Int)
+  conjure "gps1" gps1p2
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "<" ((<) :: Int -> Int -> Bool)
+    , iif (undefined :: Int)
+    , fun "undefined" (undefined :: Int)
+    , maxSize 4
+    , maxEquationSize 4
     ]
 
 
@@ -90,13 +92,14 @@
 
 gps2c :: IO ()
 gps2c  =  do
-  conjureWithMaxSize 6 "gps2" gps2p
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "*" ((*) :: Double -> Double -> Double)
-    , prim "/" ((/) :: Double -> Double -> Double)
-    , prim "+" ((+) :: Double -> Double -> Double)
-    , prim "-" ((-) :: Double -> Double -> Double)
+  conjure "gps2" gps2p
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "*" ((*) :: Double -> Double -> Double)
+    , fun "/" ((/) :: Double -> Double -> Double)
+    , fun "+" ((+) :: Double -> Double -> Double)
+    , fun "-" ((-) :: Double -> Double -> Double)
+    , maxSize 6
     ]
 
 
@@ -133,16 +136,17 @@
 
 gps4c :: IO ()
 gps4c  =  do
-  conjureFromSpecWith args{maxSize=6} "gps4" gps4s
-    [ pr '-'
-    , pr ("" :: String)
-    , prim ":" ((:) :: Char -> String -> String)
-    , prim "==" ((==) :: Char -> Char -> Bool)
-    , prim "head" (head :: String -> Char)
-    , prim "tail" (tail :: String -> String)
-    , prif (undefined :: Char)
-    , prif (undefined :: String)
-    , prim "toUpper" (toUpper :: Char -> Char)
+  conjureFromSpec "gps4" gps4s
+    [ con '-'
+    , con ("" :: String)
+    , fun ":" ((:) :: Char -> String -> String)
+    , fun "==" ((==) :: Char -> Char -> Bool)
+    , fun "head" (head :: String -> Char)
+    , fun "tail" (tail :: String -> String)
+    , iif (undefined :: Char)
+    , iif (undefined :: String)
+    , fun "toUpper" (toUpper :: Char -> Char)
+    , maxSize 6
     ]
 
 
@@ -192,25 +196,26 @@
     ]
 
   conjureFromSpec "tell" gps5s
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "`div`" (div :: Int -> Int -> Int)
-    , prim "`mod`" (mod :: Int -> Int -> Int)
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "`div`" (div :: Int -> Int -> Int)
+    , fun "`mod`" (mod :: Int -> Int -> Int)
     ]
 
   conjure "gps5" gps5p
-    [ pr coins
-    , prim "tell" tell
+    [ con coins
+    , fun "tell" tell
     ]
 
-  conjureWith args{target=50400} "gps5" gps5p
-    [ pr (1 :: Int)
-    , pr (5 :: Int)
-    , pr (10 :: Int)
-    , pr (25 :: Int)
-    , pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "tell" tell
+  conjure "gps5" gps5p
+    [ con (1 :: Int)
+    , con (5 :: Int)
+    , con (10 :: Int)
+    , con (25 :: Int)
+    , con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "tell" tell
+    , target 50400
     ]
 
 
@@ -249,17 +254,18 @@
 -- out of reach performance-wise
 gps7c :: IO ()
 gps7c  =  do
-  conjureWith args{maxSize=6} "gps7" gps7p $ take 0
-    [ pr (0 :: Integer)
-    , pr (1 :: Integer)
-    , prim "%" ((%) :: Integer -> Integer -> Rational)
-    , prim "+" ((+) :: Integer -> Integer -> Integer)
-    , prim "-" ((-) :: Integer -> Integer -> Integer)
-    , prim "*" ((*) :: Integer -> Integer -> Integer)
-    , prim "min" (min :: Integer -> Integer -> Integer)
-    , prim ".." (enumFromTo :: Integer -> Integer -> [Integer])
-    , prim "map" (map :: (Integer -> Integer) -> [Integer] -> [Integer])
-    , prim "sum" (sum :: [Integer] -> Integer)
+  conjure "gps7" gps7p $ take 0
+    [ con (0 :: Integer)
+    , con (1 :: Integer)
+    , fun "%" ((%) :: Integer -> Integer -> Rational)
+    , fun "+" ((+) :: Integer -> Integer -> Integer)
+    , fun "-" ((-) :: Integer -> Integer -> Integer)
+    , fun "*" ((*) :: Integer -> Integer -> Integer)
+    , fun "min" (min :: Integer -> Integer -> Integer)
+    , fun ".." (enumFromTo :: Integer -> Integer -> [Integer])
+    , fun "map" (map :: (Integer -> Integer) -> [Integer] -> [Integer])
+    , fun "sum" (sum :: [Integer] -> Integer)
+    , maxSize 6
     ]
 
 
@@ -319,14 +325,15 @@
 
 -- unreachable due to lambda
 gps10c :: IO ()
-gps10c  =  conjureWith args{target=50400} "gps10" gps10p
-  [ pr (0 :: Int)
-  , pr (1 :: Int)
-  , pr (2 :: Int)
-  , pr (3 :: Int)
-  , prim "`div`" (div :: Int -> Int -> Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "-" ((-) :: Int -> Int -> Int)
+gps10c  =  conjure "gps10" gps10p
+  [ con (0 :: Int)
+  , con (1 :: Int)
+  , con (2 :: Int)
+  , con (3 :: Int)
+  , fun "`div`" (div :: Int -> Int -> Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "-" ((-) :: Int -> Int -> Int)
+  , target 50400
   ]
 
 
@@ -348,8 +355,8 @@
 
 gps11c :: IO ()
 gps11c  =  conjure "gcd a b" gps11p
-  [ pr (0::Int)
-  , prim "`mod`" (mod :: Int -> Int -> Int)
+  [ con (0::Int)
+  , fun "`mod`" (mod :: Int -> Int -> Int)
   ]
   -- generated function:
   -- gcd x 0  =  x
@@ -368,9 +375,9 @@
 
 gps12c :: IO ()
 gps12c  =  conjure "gps12" gps12p
-  [ prim "findIndices" (findIndices :: (String -> Bool) -> [String] -> [Int])
-  , prim "`isPrefixOf`" (isPrefixOf :: String -> String -> Bool)
-  , prim "tails" (tails :: String -> [String])
+  [ fun "findIndices" (findIndices :: (String -> Bool) -> [String] -> [Int])
+  , fun "`isPrefixOf`" (isPrefixOf :: String -> String -> Bool)
+  , fun "tails" (tails :: String -> [String])
   ]
 
 
@@ -390,11 +397,11 @@
 
 gps13c :: IO ()
 gps13c  =  conjure "gps13_leaders" gps13p
-  [ pr ([] :: [Int])
-  , prim ":" ((:) :: Int -> [Int] -> [Int])
-  , prim ">" ((>) :: Int -> Int -> Bool)
-  , prim "all" (all :: (Int -> Bool) -> [Int] -> Bool)
-  , prif (undefined :: [Int])
+  [ con ([] :: [Int])
+  , fun ":" ((:) :: Int -> [Int] -> [Int])
+  , fun ">" ((>) :: Int -> Int -> Bool)
+  , fun "all" (all :: (Int -> Bool) -> [Int] -> Bool)
+  , iif (undefined :: [Int])
   ]
 
 
@@ -460,13 +467,13 @@
 
 gps16c :: IO ()
 gps16c  =  conjure "gps16_middle" gps16p
-  [ pr ""
-  , pr (1 :: Int)
-  , prim "<=" ((<=) :: Int -> Int -> Bool)
-  , prim ":" ((:) :: Char -> String -> String)
-  , prim "length" (length :: String -> Int)
-  , prim "init" (init :: String -> String)
-  , prif (undefined :: String)
+  [ con ""
+  , con (1 :: Int)
+  , fun "<=" ((<=) :: Int -> Int -> Bool)
+  , fun ":" ((:) :: Char -> String -> String)
+  , fun "length" (length :: String -> Int)
+  , fun "init" (init :: String -> String)
+  , iif (undefined :: String)
   ]
 
 
@@ -493,15 +500,16 @@
 -- setting limit of 5 for faster automated tests
 -- BENCHMARK: increase maxSize from 5 to 18
 gps17c :: IO ()
-gps17c  =  conjureWith args{maxSize=5} "gps17_pds" gps17p
-  [ pr (0 :: Int)
-  , prif (undefined :: Int)
-  , prim "not" not
-  , prim "null" (null :: [Int] -> Bool)
-  , prim "==" ((==) :: Int -> Int -> Bool)
-  , prim "head" (head :: [Int] -> Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "&&" (&&)
+gps17c  =  conjure "gps17_pds" gps17p
+  [ con (0 :: Int)
+  , iif (undefined :: Int)
+  , fun "not" not
+  , fun "null" (null :: [Int] -> Bool)
+  , fun "==" ((==) :: Int -> Int -> Bool)
+  , fun "head" (head :: [Int] -> Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "&&" (&&)
+  , maxSize 5
   ]
 
 
@@ -516,15 +524,16 @@
 
 -- this was OOM'd
 gps18c :: IO ()
-gps18c  =  conjureWithMaxSize 6 "gps18_price" gps18p
-  [ pr (0 :: Double)
-  , pr (1 :: Double)
-  , prim "+" ((+) :: Double -> Double -> Double)
-  , prim "*" ((*) :: Double -> Double -> Double)
-  , prim "-" ((-) :: Double -> Double -> Double)
---  , prim "foldr" (foldr :: (Double -> Double -> Double) -> Double -> [Double] -> Double)
---   , prim "zipWith" (zipWith :: (Double -> Double -> Double) -> [Double] -> [Double] -> [Double])
---  , prim "map" (map :: (Double -> Double) -> [Double] -> [Double])
+gps18c  =  conjure "gps18_price" gps18p
+  [ con (0 :: Double)
+  , con (1 :: Double)
+  , fun "+" ((+) :: Double -> Double -> Double)
+  , fun "*" ((*) :: Double -> Double -> Double)
+  , fun "-" ((-) :: Double -> Double -> Double)
+--  , fun "foldr" (foldr :: (Double -> Double -> Double) -> Double -> [Double] -> Double)
+--   , fun "zipWith" (zipWith :: (Double -> Double -> Double) -> [Double] -> [Double] -> [Double])
+--  , fun "map" (map :: (Double -> Double) -> [Double] -> [Double])
+  , maxSize 6
   ]
 
 
@@ -543,12 +552,13 @@
 -- size 14, out of reach performance wise.
 
 gps19c :: IO ()
-gps19c  =  conjureWithMaxSize 6 "gps19_snowday" gps19p
-  [ pr (0 :: Int)
-  , pr (1 :: Int)
-  , prim "max" (max :: Double -> Double -> Double)
-  , prim "+" ((+) :: Double -> Double -> Double)
-  , prim "-" ((-) :: Double -> Double -> Double)
+gps19c  =  conjure "gps19_snowday" gps19p
+  [ con (0 :: Int)
+  , con (1 :: Int)
+  , fun "max" (max :: Double -> Double -> Double)
+  , fun "+" ((+) :: Double -> Double -> Double)
+  , fun "-" ((-) :: Double -> Double -> Double)
+  , maxSize 6
   ]
 
 
@@ -587,23 +597,23 @@
 gps21c :: IO ()
 gps21c  =  do
   conjureFromSpec "spin" spinSpec
-    [ prim "length"  (length :: String -> Int)
-    , prim "reverse" (reverse :: String -> String)
-    , prif (undefined :: String)
-    , prim ">="      ((>=) :: Int -> Int -> Bool)
-    , pr (5 :: Int)
+    [ fun "length"  (length :: String -> Int)
+    , fun "reverse" (reverse :: String -> String)
+    , iif (undefined :: String)
+    , fun ">="      ((>=) :: Int -> Int -> Bool)
+    , con (5 :: Int)
     ]
 
   conjureFromSpec "gps21_spinwords" gps21s
-    [ prim "words"   words
-    , prim "unwords" unwords
-    , prim "spin"    (spin :: String -> String)
-    , prim "map"     (map :: (String -> String) -> [String] -> [String])
-    , prim "length"  (length :: String -> Int)
-    , prim "reverse" (reverse :: String -> String)
-    , prif (undefined :: String)
-    , prim ">="      ((>=) :: Int -> Int -> Bool)
-    , pr (5 :: Int)
+    [ fun "words"   words
+    , fun "unwords" unwords
+    , fun "spin"    (spin :: String -> String)
+    , fun "map"     (map :: (String -> String) -> [String] -> [String])
+    , fun "length"  (length :: String -> Int)
+    , fun "reverse" (reverse :: String -> String)
+    , iif (undefined :: String)
+    , fun ">="      ((>=) :: Int -> Int -> Bool)
+    , con (5 :: Int)
     ]
 
 
@@ -624,13 +634,14 @@
 gps22c :: IO ()
 gps22c  =  do
   -- cannot conjure at size 13, maybe beyond?
-  conjureWith args{target=10080} "digits" digits'
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "`div`" (div :: Int -> Int -> Int)
-    , prim "`mod`" (mod :: Int -> Int -> Int)
-    , prim "div10" ((`div` 10) :: Int -> Int)
-    , pr (10 :: Int)
+  conjure "digits" digits'
+    [ con ([] :: [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)
+    , target 10080
     ]
 
   conjure "gps22" gps22p
@@ -684,16 +695,16 @@
 
 gps24c :: IO ()
 gps24c  =  do
-  conjureFromSpecWith args{maxTests=360} "gps24" gps24s_twitter
-    [ pr Empty
-    , pr TooMany
-    , prim "Tweet" Tweet
-    , prif (undefined :: Twitter)
-    , pr ""
-    , prim ":" ((:) :: Char -> String -> String)
-    , prim "length" (length :: String -> Int)
-    , pr (140 :: Int)
-    , prim ">" ((>) :: Int -> Int -> Bool)
+  conjureFromSpec "gps24" gps24s_twitter
+    [ con Empty
+    , con TooMany
+    , fun "Tweet" Tweet
+    , iif (undefined :: Twitter)
+    , con ""
+    , fun ":" ((:) :: Char -> String -> String)
+    , fun "length" (length :: String -> Int)
+    , con (140 :: Int)
+    , fun ">" ((>) :: Int -> Int -> Bool)
     ]
 
 
@@ -711,15 +722,16 @@
 
 -- out of reach performance-wise
 gps25c :: IO ()
-gps25c  =  conjureWith args{maxSize=6} "gps25" gps25p
-  [ pr (0 :: Double)
-  , pr (2 :: Double)
-  , prim "+" ((+) :: Double -> Double -> Double)
-  , prim "-" ((-) :: Double -> Double -> Double)
-  , prim "**" ((**) :: Double -> Double -> Double)
-  , prim "zipWith" (zipWith :: (Double -> Double -> Double) -> [Double] -> [Double] -> [Double])
-  , prim "map" (map :: (Double -> Double) -> [Double] -> [Double])
-  , prim "sqrt" (sqrt :: Double -> Double)
+gps25c  =  conjure "gps25" gps25p
+  [ con (0 :: Double)
+  , con (2 :: Double)
+  , fun "+" ((+) :: Double -> Double -> Double)
+  , fun "-" ((-) :: Double -> Double -> Double)
+  , fun "**" ((**) :: Double -> Double -> Double)
+  , fun "zipWith" (zipWith :: (Double -> Double -> Double) -> [Double] -> [Double] -> [Double])
+  , fun "map" (map :: (Double -> Double) -> [Double] -> [Double])
+  , fun "sqrt" (sqrt :: Double -> Double)
+  , maxSize 6
   ]
 
 
diff --git a/bench/gps2.txt b/bench/gps2.txt
--- a/bench/gps2.txt
+++ b/bench/gps2.txt
@@ -36,7 +36,7 @@
 -- 11 candidates of size 3
 -- 29 candidates of size 4
 -- tested 44 candidates
-cannot conjure
+gps1  =  undefined  -- search exhausted
 
 gps2 :: Double -> Double -> Int -> Double
 -- testing 5 combinations of argument values
@@ -48,14 +48,10 @@
 -- 256 candidates of size 5
 -- 1252 candidates of size 6
 -- tested 1592 candidates
-cannot conjure
+gps2  =  undefined  -- search exhausted
 
 gps3 :: [Char] -> Int
--- pruning with 0/0 rules
--- 0 candidates of size 1
--- 0 candidates of size 2
--- tested 0 candidates
-cannot conjure
+gps3  =  error "could not reify specification, suggestion: conjureFromSpec"
 
 gps4 :: [Char] -> [Char]
 -- pruning with 13/21 rules
@@ -66,14 +62,14 @@
 -- 51 candidates of size 5
 -- 119 candidates of size 6
 -- tested 203 candidates
-cannot conjure
+gps4  =  undefined  -- search exhausted
 
 gps5 :: Int -> [Int]
 -- testing 6 combinations of argument values
 -- pruning with 0/0 rules
 -- 0 candidates of size 1
 -- tested 0 candidates
-cannot conjure
+gps5  =  undefined  -- search exhausted
 
 tell :: [Int] -> Int -> [Int]
 -- pruning with 0/0 rules
@@ -123,14 +119,14 @@
 -- 0 candidates of size 1
 -- 0 candidates of size 2
 -- tested 0 candidates
-cannot conjure
+gps6  =  undefined  -- search exhausted
 
 gps7 :: Integer -> Integer -> Ratio Integer
 -- testing 6 combinations of argument values
 -- pruning with 0/0 rules
 -- 0 candidates of size 1
 -- tested 0 candidates
-cannot conjure
+gps7  =  undefined  -- search exhausted
 
 gps8 :: Int -> [Int] -> (Int,Int)
 -- testing 3 combinations of argument values
@@ -138,14 +134,14 @@
 -- 0 candidates of size 1
 -- 0 candidates of size 2
 -- tested 0 candidates
-cannot conjure
+gps8  =  undefined  -- search exhausted
 
 gps9 :: Int -> [Char]
 -- testing 7 combinations of argument values
 -- pruning with 0/0 rules
 -- 0 candidates of size 1
 -- tested 0 candidates
-cannot conjure
+gps9  =  undefined  -- search exhausted
 
 gps10 :: [Int] -> Int
 -- testing 7 combinations of argument values
@@ -161,7 +157,7 @@
 -- 30712 candidates of size 9
 -- tested 7064 candidates
 gps10 []  =  0
-gps10 (x:xs)  =  gps10 xs + (x `div` 3 - 2)
+gps10 (x:xs)  =  (x `div` 3 - 2) + gps10 xs
 
 gcd :: Int -> Int -> Int
 -- testing 11 combinations of argument values
@@ -209,17 +205,10 @@
                          else gps13_leaders xs
 
 gps14_luhn :: [Int] -> Int
--- pruning with 0/0 rules
--- 0 candidates of size 1
--- 0 candidates of size 2
--- tested 0 candidates
-cannot conjure
+gps14_luhn  =  error "could not reify specification, suggestion: conjureFromSpec"
 
 gps15_mastermind :: () -> ()
--- pruning with 0/1 rules
--- 1 candidates of size 1
--- tested 1 candidates
-gps15_mastermind u  =  u
+gps15_mastermind  =  error "could not reify specification, suggestion: conjureFromSpec"
 
 gps16_middle :: [Char] -> [Char]
 -- testing 7 combinations of argument values
@@ -251,7 +240,7 @@
 -- 0 candidates of size 4
 -- 2 candidates of size 5
 -- tested 4 candidates
-cannot conjure
+gps17_pds  =  undefined  -- search exhausted
 
 gps18_price :: [Double] -> [Double] -> Double
 -- testing 4 combinations of argument values
@@ -263,7 +252,7 @@
 -- 33 candidates of size 5
 -- 176 candidates of size 6
 -- tested 213 candidates
-cannot conjure
+gps18_price  =  undefined  -- search exhausted
 
 gps19_snowday :: Int -> Double -> Double -> Double -> Double
 -- testing 7 combinations of argument values
@@ -275,14 +264,10 @@
 -- 312 candidates of size 5
 -- 659 candidates of size 6
 -- tested 1036 candidates
-cannot conjure
+gps19_snowday  =  undefined  -- search exhausted
 
 gps20 :: [Char] -> Bool
--- pruning with 0/0 rules
--- 0 candidates of size 1
--- 0 candidates of size 2
--- tested 0 candidates
-cannot conjure
+gps20  =  error "could not reify specification, suggestion: conjureFromSpec"
 
 spin :: [Char] -> [Char]
 -- pruning with 6/6 rules
@@ -326,13 +311,10 @@
 -- 923 candidates of size 10
 -- 8902 candidates of size 11
 -- tested 10900 candidates
-cannot conjure
+digits  =  undefined  -- search exhausted
 
 gps22 :: Int -> [Char]
--- pruning with 0/0 rules
--- 0 candidates of size 1
--- tested 0 candidates
-cannot conjure
+gps22  =  error "could not reify specification, suggestion: conjureFromSpec"
 
 gps23 :: [Char] -> [Char] -> [Char] -> [Char]
 -- pruning with 0/0 rules
@@ -348,7 +330,7 @@
 -- 2722 candidates of size 10
 -- 5292 candidates of size 11
 -- tested 10955 candidates
-cannot conjure
+gps23  =  undefined  -- search exhausted
 
 gps24 :: [Char] -> Twitter
 -- pruning with 4/8 rules
@@ -381,5 +363,5 @@
 -- 76 candidates of size 5
 -- 438 candidates of size 6
 -- tested 532 candidates
-cannot conjure
+gps25  =  undefined  -- search exhausted
 
diff --git a/bench/ill-hit.hs b/bench/ill-hit.hs
--- a/bench/ill-hit.hs
+++ b/bench/ill-hit.hs
@@ -24,19 +24,23 @@
 
 main :: IO ()
 main  =  do
+  -- the following conjures from an "empty" spec
+  -- we should get a proper error message
+  conjure "sum" (undefined :: [Int] -> Int) ingredients
+
   -- the following does not hit all 6 defined prims, only 4
-  conjure "sum" (sum' :: [Int] -> Int) primitives
+  conjure "sum" (sum' :: [Int] -> Int) ingredients
 
   -- the following conjures from a spec
-  conjureFromSpec "sum" sumSpec primitives
+  conjureFromSpec "sum" sumSpec ingredients
 
-primitives :: [Prim]
-primitives =
-  [ pr (0 :: Int)
-  , pr (1 :: Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "*" ((*) :: Int -> Int -> Int)
-  , prim "null" (null :: [Int] -> Bool)
-  , prim "head" (head :: [Int] -> Int)
-  , prim "tail" (tail :: [Int] -> [Int])
+ingredients :: [Ingredient]
+ingredients =
+  [ con (0 :: Int)
+  , con (1 :: Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "*" ((*) :: Int -> Int -> Int)
+  , fun "null" (null :: [Int] -> Bool)
+  , fun "head" (head :: [Int] -> Int)
+  , fun "tail" (tail :: [Int] -> [Int])
   ]
diff --git a/bench/ill-hit.txt b/bench/ill-hit.txt
--- a/bench/ill-hit.txt
+++ b/bench/ill-hit.txt
@@ -1,4 +1,7 @@
 sum :: [Int] -> Int
+sum  =  error "could not reify specification, suggestion: conjureFromSpec"
+
+sum :: [Int] -> Int
 -- testing 4 combinations of argument values
 -- pruning with 14/25 rules
 -- 2 candidates of size 1
diff --git a/bench/lowtests.hs b/bench/lowtests.hs
--- a/bench/lowtests.hs
+++ b/bench/lowtests.hs
@@ -54,33 +54,42 @@
 replicates' [a,b]   3  =  [a,a,a,b,b,b]
 replicates' [a,b,c] 3  =  [a,a,a,b,b,b,c,c,c]
 
-as :: Args
-as  =  args{showTheory = True, maxSize = 18}
-
 main :: IO ()
 main = do
   -- low number of tests, cannot conjure due to incorrect property
-  conjureWith as{maxTests=60} "subset" (subset')
-    [ prim "sort" (sort :: [Int] -> [Int])
-    , prim "`isSubsequenceOf`" (isSubsequenceOf :: [Int] -> [Int] -> Bool)
+  conjure "subset" subset'
+    [ fun "sort" (sort :: [Int] -> [Int])
+    , fun "`isSubsequenceOf`" (isSubsequenceOf :: [Int] -> [Int] -> Bool)
+    , showTheory
+    , maxSize 18
+    , maxTests 60
     ]
 
   -- subset xs ys  =  sort xs `isSubsequenceOf` sort ys
-  conjureWith as{maxTests=360} "subset" (subset')
-    [ prim "sort" (sort :: [Int] -> [Int])
-    , prim "`isSubsequenceOf`" (isSubsequenceOf :: [Int] -> [Int] -> Bool)
+  conjure "subset" (subset')
+    [ fun "sort" (sort :: [Int] -> [Int])
+    , fun "`isSubsequenceOf`" (isSubsequenceOf :: [Int] -> [Int] -> Bool)
+    , showTheory
+    , maxSize 18
+    , maxTests 360
     ]
 
   -- low number of tests, cannot conjure due to incorrect property
-  conjureWith as{maxTests=60} "replicates" replicates'
-    [ prim "replicate" (replicate :: Int -> String -> [String])
-    , prim "transpose" (transpose :: [[Char]] -> [[Char]])
-    , prim "concat"    (concat :: [String] -> String)
+  conjure "replicates" replicates'
+    [ fun "replicate" (replicate :: Int -> String -> [String])
+    , fun "transpose" (transpose :: [[Char]] -> [[Char]])
+    , fun "concat"    (concat :: [String] -> String)
+    , showTheory
+    , maxSize 18
+    , maxTests 60
     ]
 
   -- emulates how MagicHaskeller generates "replicates"
-  conjureWith as{maxTests=360} "replicates" replicates'
-    [ prim "replicate" (replicate :: Int -> String -> [String])
-    , prim "transpose" (transpose :: [[Char]] -> [[Char]])
-    , prim "concat"    (concat :: [String] -> String)
+  conjure "replicates" replicates'
+    [ fun "replicate" (replicate :: Int -> String -> [String])
+    , fun "transpose" (transpose :: [[Char]] -> [[Char]])
+    , fun "concat"    (concat :: [String] -> String)
+    , showTheory
+    , maxSize 18
+    , maxTests 360
     ]
diff --git a/bench/lowtests.txt b/bench/lowtests.txt
--- a/bench/lowtests.txt
+++ b/bench/lowtests.txt
@@ -32,7 +32,7 @@
 -- 0 candidates of size 17
 -- 0 candidates of size 18
 -- tested 27 candidates
-cannot conjure
+subset  =  undefined  -- search exhausted
 
 subset :: [Int] -> [Int] -> Bool
 -- testing 44 combinations of argument values
@@ -80,7 +80,7 @@
 -- 0 candidates of size 17
 -- 0 candidates of size 18
 -- tested 6 candidates
-cannot conjure
+replicates  =  undefined  -- search exhausted
 
 replicates :: [Char] -> Int -> [Char]
 -- testing 360 combinations of argument values
diff --git a/bench/p12.hs b/bench/p12.hs
--- a/bench/p12.hs
+++ b/bench/p12.hs
@@ -1,13 +1,10 @@
--- 12 background primitives
+-- 12 background ingredients
 --
 -- Copyright (C) 2021-2025 Rudy Matela
 -- Distributed under the 3-Clause BSD licence (see the file LICENSE).
 import Conjure
 import System.Environment
 
-conjureT :: Conjurable f => String -> f -> [Prim] -> IO ()
-conjureT  =  conjureWith args{maxSize=1}
-
 factorial :: Int -> Int
 factorial 0  =  1
 factorial 1  =  1
@@ -33,42 +30,42 @@
 
 main :: IO ()
 main  =  do
-  putStrLn $ "running with " ++ show (length primitives) ++ " primitives"
+  putStrLn $ "running with " ++ show (length ingredients) ++ " ingredients"
   as <- getArgs
   case as of
-    ["factorial"]     -> conjure  "factorial n" factorial primitives
-    ["factorial","t"] -> conjureT "factorial n" factorial primitives
-    ["sum"]           -> conjure  "sum"     (sum     :: [Int] -> Int) primitives
-    ["sum","t"]       -> conjureT "sum"     (sum     :: [Int] -> Int) primitives
-    ["product"]       -> conjure  "product" (product :: [Int] -> Int) primitives
-    ["product","t"]   -> conjureT "product" (product :: [Int] -> Int) primitives
-    ["length"]        -> conjure  "length"  (length  :: [Int] -> Int) primitives
-    ["length","t"]    -> conjureT "length"  (length  :: [Int] -> Int) primitives
-    ["count"]         -> conjure  "count"   count' $ primitives ++ primsCount
-    ["count","t"]     -> conjureT "count"   count' $ primitives ++ primsCount
-    _                 -> conjure  "factorial n" factorial primitives
+    ["factorial"]     -> conjure "factorial n" factorial   ingredients
+    ["factorial","t"] -> conjure "factorial n" factorial $ ingredients ++ [maxSize 1]
+    ["sum"]           -> conjure "sum"     (sum     :: [Int] -> Int)   ingredients
+    ["sum","t"]       -> conjure "sum"     (sum     :: [Int] -> Int) $ ingredients ++ [maxSize 1]
+    ["product"]       -> conjure "product" (product :: [Int] -> Int)   ingredients
+    ["product","t"]   -> conjure "product" (product :: [Int] -> Int) $ ingredients ++ [maxSize 1]
+    ["length"]        -> conjure "length"  (length  :: [Int] -> Int)   ingredients
+    ["length","t"]    -> conjure "length"  (length  :: [Int] -> Int) $ ingredients ++ [maxSize 1]
+    ["count"]         -> conjure "count"   count' $ ingredients ++ primsCount
+    ["count","t"]     -> conjure "count"   count' $ ingredients ++ primsCount ++ [maxSize 1]
+    _                 -> conjure "factorial n" factorial ingredients
 
-primitives :: [Prim]
-primitives  =
-  [ pr (0::Int)
-  , pr (1::Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "*" ((*) :: Int -> Int -> Int)
-  , prim "dec" (subtract 1 :: Int -> Int)
+ingredients :: [Ingredient]
+ingredients  =
+  [ con (0::Int)
+  , con (1::Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "*" ((*) :: Int -> Int -> Int)
+  , fun "dec" (subtract 1 :: Int -> Int)
 
-  , prim "==" ((==) :: Int -> Int -> Bool)
+  , fun "==" ((==) :: Int -> Int -> Bool)
 
-  , pr ([] :: [Int])
-  , prim ":" ((:) :: Int -> [Int] -> [Int])
-  , prim "head" (head :: [Int] -> Int)
-  , prim "tail" (tail :: [Int] -> [Int])
-  , prim "null" (null :: [Int] -> Bool)
-  , prim "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
-  , prim ".." (enumFromTo :: Int -> Int -> [Int])
+  , con ([] :: [Int])
+  , fun ":" ((:) :: Int -> [Int] -> [Int])
+  , fun "head" (head :: [Int] -> Int)
+  , fun "tail" (tail :: [Int] -> [Int])
+  , fun "null" (null :: [Int] -> Bool)
+  , fun "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
+  , fun ".." (enumFromTo :: Int -> Int -> [Int])
   ]
 
-primsCount :: [Prim]
+primsCount :: [Ingredient]
 primsCount  =
-  [ prim "length" (length :: [Int] -> Int)
-  , prim "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])
+  [ fun "length" (length :: [Int] -> Int)
+  , fun "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])
   ]
diff --git a/bench/p12.txt b/bench/p12.txt
--- a/bench/p12.txt
+++ b/bench/p12.txt
@@ -1,4 +1,4 @@
-running with 13 primitives
+running with 13 ingredients
 factorial :: Int -> Int
 -- testing 6 combinations of argument values
 -- pruning with 67/101 rules
diff --git a/bench/p30.hs b/bench/p30.hs
--- a/bench/p30.hs
+++ b/bench/p30.hs
@@ -1,13 +1,10 @@
--- 30 background primitives, does Conjure scale?
+-- 30 background ingredients, does Conjure scale?
 --
 -- Copyright (C) 2021-2025 Rudy Matela
 -- Distributed under the 3-Clause BSD licence (see the file LICENSE).
 import Conjure
 import System.Environment
 
-conjureT :: Conjurable f => String -> f -> [Prim] -> IO ()
-conjureT  =  conjureWith args{maxSize=1}
-
 factorial :: Int -> Int
 factorial 0  =  1
 factorial 1  =  1
@@ -33,58 +30,58 @@
 
 main :: IO ()
 main  =  do
-  putStrLn $ "running with " ++ show (length primitives) ++ " primitives"
+  putStrLn $ "running with " ++ show (length ingredients) ++ " ingredients"
   as <- getArgs
   case as of
-    ["factorial"]     -> conjure  "factorial n" factorial primitives
-    ["factorial","t"] -> conjureT "factorial n" factorial primitives
-    ["sum"]           -> conjure  "sum"     (sum     :: [Int] -> Int) primitives
-    ["sum","t"]       -> conjureT "sum"     (sum     :: [Int] -> Int) primitives
-    ["product"]       -> conjure  "product" (product :: [Int] -> Int) primitives
-    ["product","t"]   -> conjureT "product" (product :: [Int] -> Int) primitives
-    ["length"]        -> conjure  "length"  (length  :: [Int] -> Int) primitives
-    ["length","t"]    -> conjureT "length"  (length  :: [Int] -> Int) primitives
-    ["count"]         -> conjure  "count"   count' $ primitives ++ primsLength
-    ["count","t"]     -> conjureT "count"   count' $ primitives ++ primsLength
+    ["factorial"]     -> conjure "factorial n" factorial   ingredients
+    ["factorial","t"] -> conjure "factorial n" factorial $ ingredients ++ [maxSize 1]
+    ["sum"]           -> conjure "sum"     (sum     :: [Int] -> Int)   ingredients
+    ["sum","t"]       -> conjure "sum"     (sum     :: [Int] -> Int) $ ingredients ++ [maxSize 1]
+    ["product"]       -> conjure "product" (product :: [Int] -> Int)   ingredients
+    ["product","t"]   -> conjure "product" (product :: [Int] -> Int) $ ingredients ++ [maxSize 1]
+    ["length"]        -> conjure "length"  (length  :: [Int] -> Int)   ingredients
+    ["length","t"]    -> conjure "length"  (length  :: [Int] -> Int) $ ingredients ++ [maxSize 1]
+    ["count"]         -> conjure "count"   count' $ ingredients ++ primsLength
+    ["count","t"]     -> conjure "count"   count' $ ingredients ++ primsLength ++ [maxSize 1]
     _                 -> putStrLn "usage: p30 <factorial|sum|product|length|count> [t]"
 
-primitives :: [Prim]
-primitives  =
-  [ pr False
-  , pr True
-  , prim "&&" (&&)
-  , prim "||" (||)
-  , prim "not" not
+ingredients :: [Ingredient]
+ingredients  =
+  [ con False
+  , con True
+  , fun "&&" (&&)
+  , fun "||" (||)
+  , fun "not" not
 
-  , pr (0::Int)
-  , pr (1::Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "*" ((*) :: Int -> Int -> Int)
-  , prim "dec" (subtract 1 :: Int -> Int)
-  , prim "-" ((-) :: Int -> Int -> Int)
+  , con (0::Int)
+  , con (1::Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "*" ((*) :: Int -> Int -> Int)
+  , fun "dec" (subtract 1 :: Int -> Int)
+  , fun "-" ((-) :: Int -> Int -> Int)
 
-  , prim "==" ((==) :: Int -> Int -> Bool)
-  , prim "<=" ((<=) :: Int -> Int -> Bool)
-  , prim "<"  ((<) :: Int -> Int -> Bool)
+  , fun "==" ((==) :: Int -> Int -> Bool)
+  , fun "<=" ((<=) :: Int -> Int -> Bool)
+  , fun "<"  ((<) :: Int -> Int -> Bool)
 
-  , prim "const" (const :: Int -> Int -> Int)
+  , fun "const" (const :: Int -> Int -> Int)
 
-  , pr ([] :: [Int])
-  , prim ":" ((:) :: Int -> [Int] -> [Int])
-  , prim "head" (head :: [Int] -> Int)
-  , prim "tail" (tail :: [Int] -> [Int])
-  , prim "null" (null :: [Int] -> Bool)
-  , prim "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
+  , con ([] :: [Int])
+  , fun ":" ((:) :: Int -> [Int] -> [Int])
+  , fun "head" (head :: [Int] -> Int)
+  , fun "tail" (tail :: [Int] -> [Int])
+  , fun "null" (null :: [Int] -> Bool)
+  , fun "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
 
-  , prim "map" (map :: (Int -> Int) -> [Int] -> [Int])
-  , prim "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])
-  , prim ".." (enumFromTo :: Int -> Int -> [Int])
+  , fun "map" (map :: (Int -> Int) -> [Int] -> [Int])
+  , fun "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])
+  , fun ".." (enumFromTo :: Int -> Int -> [Int])
 
-  , prim "++" ((++) :: [Int] -> [Int] -> [Int])
-  , prim "elem" (elem :: Int -> [Int] -> Bool)
+  , fun "++" ((++) :: [Int] -> [Int] -> [Int])
+  , fun "elem" (elem :: Int -> [Int] -> Bool)
   ]
 
-primsLength :: [Prim]
+primsLength :: [Ingredient]
 primsLength =
-  [ prim "length" (length :: [Int] -> Int)
+  [ fun "length" (length :: [Int] -> Int)
   ]
diff --git a/bench/p30.txt b/bench/p30.txt
--- a/bench/p30.txt
+++ b/bench/p30.txt
@@ -1,2 +1,2 @@
-running with 26 primitives
+running with 26 ingredients
 usage: p30 <factorial|sum|product|length|count> [t]
diff --git a/bench/redundants.hs b/bench/redundants.hs
--- a/bench/redundants.hs
+++ b/bench/redundants.hs
@@ -20,8 +20,8 @@
 -- * maximum candidate size (5 = few seconds, 7 = few minutes);
 -- * function name (for pretty-printing purposes);
 -- * proxy value to indicate the type of functions to generate;
--- * list of primitives, in Conjure-compatible form.
-printRedundantCandidates :: Conjurable f => Int -> String -> f -> [Prim] -> IO ()
+-- * list of ingredients, in Conjure-compatible form.
+printRedundantCandidates :: Conjurable f => Int -> String -> f -> [Ingredient] -> IO ()
 printRedundantCandidates n nm f ps  =  do
   putStrLn $ "Redundant candidates for: " ++ nm ++ " :: " ++ show (typeOf f)
   putStrLn $ "  pruning with " ++ show nRules ++ "/" ++ show nREs ++ " rules"
@@ -40,7 +40,7 @@
   css            =  take n
                  .  discardT isRedundantByIntroduction -- additional pruning rule
                  $  css'
-  (css', thy, _, _) =  candidateDefnsC args nm f ps  -- Conjure uses this for listing candidates
+  (css', thy, _, _) =  candidateDefns nm f ps  -- Conjure uses this for listing candidates
   nRules         =  length (rules thy)
   nREs           =  length (equations thy) + nRules
   maxTests       =  60 -- a hardcoded value probably will not hurt in this simple benchmark
@@ -66,46 +66,46 @@
   -- We can also customize the n per-function below:
 
   printRedundantCandidates (n+1) "foo" (undefined :: Int -> Int)
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
     ]
 
   printRedundantCandidates n "?" (undefined :: Int -> Int -> Int)
-    [ pr (0 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "dec" (subtract 1 :: Int -> Int)
+    [ con (0 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "dec" (subtract 1 :: Int -> Int)
     ]
 
   printRedundantCandidates (n+1) "goo" (undefined :: [Int] -> [Int])
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
     ]
 
   printRedundantCandidates n "??" (undefined :: [Int] -> [Int] -> [Int])
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
     ]
 
   printRedundantCandidates (n+1) "ton" (undefined :: Bool -> Bool)
-    [ pr False
-    , pr True
-    , prim "&&" (&&)
-    , prim "||" (||)
-    , prim "not" not
+    [ con False
+    , con True
+    , fun "&&" (&&)
+    , fun "||" (||)
+    , fun "not" not
     ]
 
   printRedundantCandidates n "&|" (undefined :: Bool -> Bool -> Bool)
-    [ pr False
-    , pr True
-    , prim "&&" (&&)
-    , prim "||" (||)
-    , prim "not" not
+    [ con False
+    , con True
+    , fun "&&" (&&)
+    , fun "||" (||)
+    , fun "not" not
     ]
 
   -- Degenerate case:
@@ -115,7 +115,7 @@
   -- through other means
   {-
   printRedundantCandidates n "gcd" (undefined :: Int -> Int -> Int)
-    [ pr (0::Int)
-    , prim "`mod`" (mod :: Int -> Int -> Int)
+    [ con (0::Int)
+    , fun "`mod`" (mod :: Int -> Int -> Int)
     ]
   -}
diff --git a/bench/runtime/lapmatrud/bench/candidates.runtime b/bench/runtime/lapmatrud/bench/candidates.runtime
--- a/bench/runtime/lapmatrud/bench/candidates.runtime
+++ b/bench/runtime/lapmatrud/bench/candidates.runtime
@@ -1,1 +1,1 @@
-9.2
+10.0
diff --git a/bench/runtime/lapmatrud/bench/carry-on.runtime b/bench/runtime/lapmatrud/bench/carry-on.runtime
--- a/bench/runtime/lapmatrud/bench/carry-on.runtime
+++ b/bench/runtime/lapmatrud/bench/carry-on.runtime
@@ -1,1 +1,1 @@
-2.4
+2.6
diff --git a/bench/runtime/lapmatrud/bench/erroneous.runtime b/bench/runtime/lapmatrud/bench/erroneous.runtime
--- a/bench/runtime/lapmatrud/bench/erroneous.runtime
+++ b/bench/runtime/lapmatrud/bench/erroneous.runtime
@@ -1,1 +1,1 @@
-2.9
+3.1
diff --git a/bench/runtime/lapmatrud/bench/gps.runtime b/bench/runtime/lapmatrud/bench/gps.runtime
--- a/bench/runtime/lapmatrud/bench/gps.runtime
+++ b/bench/runtime/lapmatrud/bench/gps.runtime
@@ -1,1 +1,1 @@
-14.7
+15.8
diff --git a/bench/runtime/lapmatrud/bench/gps2.runtime b/bench/runtime/lapmatrud/bench/gps2.runtime
--- a/bench/runtime/lapmatrud/bench/gps2.runtime
+++ b/bench/runtime/lapmatrud/bench/gps2.runtime
@@ -1,1 +1,1 @@
-11.8
+12.7
diff --git a/bench/runtime/lapmatrud/bench/ill-hit.runtime b/bench/runtime/lapmatrud/bench/ill-hit.runtime
--- a/bench/runtime/lapmatrud/bench/ill-hit.runtime
+++ b/bench/runtime/lapmatrud/bench/ill-hit.runtime
@@ -1,1 +1,1 @@
-0.5
+0.7
diff --git a/bench/runtime/lapmatrud/bench/lowtests.runtime b/bench/runtime/lapmatrud/bench/lowtests.runtime
--- a/bench/runtime/lapmatrud/bench/lowtests.runtime
+++ b/bench/runtime/lapmatrud/bench/lowtests.runtime
@@ -1,1 +1,1 @@
-0.4
+0.5
diff --git a/bench/runtime/lapmatrud/bench/p12.runtime b/bench/runtime/lapmatrud/bench/p12.runtime
--- a/bench/runtime/lapmatrud/bench/p12.runtime
+++ b/bench/runtime/lapmatrud/bench/p12.runtime
@@ -1,1 +1,1 @@
-1.6
+1.7
diff --git a/bench/runtime/lapmatrud/bench/redundants.runtime b/bench/runtime/lapmatrud/bench/redundants.runtime
--- a/bench/runtime/lapmatrud/bench/redundants.runtime
+++ b/bench/runtime/lapmatrud/bench/redundants.runtime
@@ -1,1 +1,1 @@
-3.0
+3.2
diff --git a/bench/runtime/lapmatrud/bench/strategies.runtime b/bench/runtime/lapmatrud/bench/strategies.runtime
--- a/bench/runtime/lapmatrud/bench/strategies.runtime
+++ b/bench/runtime/lapmatrud/bench/strategies.runtime
@@ -1,1 +1,1 @@
-4.6
+6.0
diff --git a/bench/runtime/lapmatrud/bench/terpret.runtime b/bench/runtime/lapmatrud/bench/terpret.runtime
--- a/bench/runtime/lapmatrud/bench/terpret.runtime
+++ b/bench/runtime/lapmatrud/bench/terpret.runtime
@@ -1,1 +1,1 @@
-7.3
+7.7
diff --git a/bench/runtime/lapmatrud/bench/unique.runtime b/bench/runtime/lapmatrud/bench/unique.runtime
--- a/bench/runtime/lapmatrud/bench/unique.runtime
+++ b/bench/runtime/lapmatrud/bench/unique.runtime
@@ -1,1 +1,1 @@
-2.4
+2.5
diff --git a/bench/runtime/lapmatrud/bench/weird.runtime b/bench/runtime/lapmatrud/bench/weird.runtime
--- a/bench/runtime/lapmatrud/bench/weird.runtime
+++ b/bench/runtime/lapmatrud/bench/weird.runtime
@@ -1,1 +1,1 @@
-2.5
+2.6
diff --git a/bench/runtime/lapmatrud/eg/arith.runtime b/bench/runtime/lapmatrud/eg/arith.runtime
--- a/bench/runtime/lapmatrud/eg/arith.runtime
+++ b/bench/runtime/lapmatrud/eg/arith.runtime
@@ -1,1 +1,1 @@
-0.9
+1.0
diff --git a/bench/runtime/lapmatrud/eg/bits.runtime b/bench/runtime/lapmatrud/eg/bits.runtime
--- a/bench/runtime/lapmatrud/eg/bits.runtime
+++ b/bench/runtime/lapmatrud/eg/bits.runtime
@@ -1,1 +1,1 @@
-3.0
+3.2
diff --git a/bench/runtime/lapmatrud/eg/bools.runtime b/bench/runtime/lapmatrud/eg/bools.runtime
--- a/bench/runtime/lapmatrud/eg/bools.runtime
+++ b/bench/runtime/lapmatrud/eg/bools.runtime
@@ -1,1 +1,1 @@
-1.6
+1.9
diff --git a/bench/runtime/lapmatrud/eg/bst.runtime b/bench/runtime/lapmatrud/eg/bst.runtime
--- a/bench/runtime/lapmatrud/eg/bst.runtime
+++ b/bench/runtime/lapmatrud/eg/bst.runtime
@@ -1,1 +1,1 @@
-4.3
+4.8
diff --git a/bench/runtime/lapmatrud/eg/count.runtime b/bench/runtime/lapmatrud/eg/count.runtime
--- a/bench/runtime/lapmatrud/eg/count.runtime
+++ b/bench/runtime/lapmatrud/eg/count.runtime
@@ -1,1 +1,1 @@
-0.5
+0.8
diff --git a/bench/runtime/lapmatrud/eg/dupos.runtime b/bench/runtime/lapmatrud/eg/dupos.runtime
--- a/bench/runtime/lapmatrud/eg/dupos.runtime
+++ b/bench/runtime/lapmatrud/eg/dupos.runtime
@@ -1,1 +1,1 @@
-1.9
+2.2
diff --git a/bench/runtime/lapmatrud/eg/either.runtime b/bench/runtime/lapmatrud/eg/either.runtime
--- a/bench/runtime/lapmatrud/eg/either.runtime
+++ b/bench/runtime/lapmatrud/eg/either.runtime
@@ -1,1 +1,1 @@
-0.1
+0.2
diff --git a/bench/runtime/lapmatrud/eg/factorial.runtime b/bench/runtime/lapmatrud/eg/factorial.runtime
--- a/bench/runtime/lapmatrud/eg/factorial.runtime
+++ b/bench/runtime/lapmatrud/eg/factorial.runtime
@@ -1,1 +1,1 @@
-1.4
+1.6
diff --git a/bench/runtime/lapmatrud/eg/fib01.runtime b/bench/runtime/lapmatrud/eg/fib01.runtime
--- a/bench/runtime/lapmatrud/eg/fib01.runtime
+++ b/bench/runtime/lapmatrud/eg/fib01.runtime
@@ -1,1 +1,1 @@
-0.5
+0.6
diff --git a/bench/runtime/lapmatrud/eg/fibonacci.runtime b/bench/runtime/lapmatrud/eg/fibonacci.runtime
--- a/bench/runtime/lapmatrud/eg/fibonacci.runtime
+++ b/bench/runtime/lapmatrud/eg/fibonacci.runtime
@@ -1,1 +1,1 @@
-3.2
+3.5
diff --git a/bench/runtime/lapmatrud/eg/higher.runtime b/bench/runtime/lapmatrud/eg/higher.runtime
--- a/bench/runtime/lapmatrud/eg/higher.runtime
+++ b/bench/runtime/lapmatrud/eg/higher.runtime
@@ -1,1 +1,1 @@
-0.8
+1.4
diff --git a/bench/runtime/lapmatrud/eg/ints.runtime b/bench/runtime/lapmatrud/eg/ints.runtime
--- a/bench/runtime/lapmatrud/eg/ints.runtime
+++ b/bench/runtime/lapmatrud/eg/ints.runtime
@@ -1,1 +1,1 @@
-0.5
+1.2
diff --git a/bench/runtime/lapmatrud/eg/maybe.runtime b/bench/runtime/lapmatrud/eg/maybe.runtime
--- a/bench/runtime/lapmatrud/eg/maybe.runtime
+++ b/bench/runtime/lapmatrud/eg/maybe.runtime
@@ -1,1 +1,1 @@
-0.3
+0.4
diff --git a/bench/runtime/lapmatrud/eg/oddeven.runtime b/bench/runtime/lapmatrud/eg/oddeven.runtime
--- a/bench/runtime/lapmatrud/eg/oddeven.runtime
+++ b/bench/runtime/lapmatrud/eg/oddeven.runtime
@@ -1,1 +1,1 @@
-1.5
+1.6
diff --git a/bench/runtime/lapmatrud/eg/pow.runtime b/bench/runtime/lapmatrud/eg/pow.runtime
--- a/bench/runtime/lapmatrud/eg/pow.runtime
+++ b/bench/runtime/lapmatrud/eg/pow.runtime
@@ -1,1 +1,1 @@
-2.8
+3.0
diff --git a/bench/runtime/lapmatrud/eg/sort.runtime b/bench/runtime/lapmatrud/eg/sort.runtime
--- a/bench/runtime/lapmatrud/eg/sort.runtime
+++ b/bench/runtime/lapmatrud/eg/sort.runtime
@@ -1,1 +1,1 @@
-3.1
+3.4
diff --git a/bench/runtime/lapmatrud/eg/these.runtime b/bench/runtime/lapmatrud/eg/these.runtime
--- a/bench/runtime/lapmatrud/eg/these.runtime
+++ b/bench/runtime/lapmatrud/eg/these.runtime
@@ -1,1 +1,1 @@
-1.7
+1.9
diff --git a/bench/runtime/lapmatrud/eg/tree.runtime b/bench/runtime/lapmatrud/eg/tree.runtime
--- a/bench/runtime/lapmatrud/eg/tree.runtime
+++ b/bench/runtime/lapmatrud/eg/tree.runtime
@@ -1,1 +1,1 @@
-1.4
+1.5
diff --git a/bench/runtime/lapmatrud/eg/tri.runtime b/bench/runtime/lapmatrud/eg/tri.runtime
--- a/bench/runtime/lapmatrud/eg/tri.runtime
+++ b/bench/runtime/lapmatrud/eg/tri.runtime
@@ -1,1 +1,1 @@
-0.2
+0.3
diff --git a/bench/runtime/lapmatrud/eg/tuple.runtime b/bench/runtime/lapmatrud/eg/tuple.runtime
--- a/bench/runtime/lapmatrud/eg/tuple.runtime
+++ b/bench/runtime/lapmatrud/eg/tuple.runtime
@@ -1,1 +1,1 @@
-0.5
+0.8
diff --git a/bench/runtime/lapmatrud/versions b/bench/runtime/lapmatrud/versions
--- a/bench/runtime/lapmatrud/versions
+++ b/bench/runtime/lapmatrud/versions
@@ -1,4 +1,4 @@
-GHC 9.2.8
+GHC 9.4.8
 leancheck-1.0.2
 express-1.0.18
 speculate-0.4.20
diff --git a/bench/runtime/zero/bench/candidates.runtime b/bench/runtime/zero/bench/candidates.runtime
--- a/bench/runtime/zero/bench/candidates.runtime
+++ b/bench/runtime/zero/bench/candidates.runtime
@@ -1,1 +1,1 @@
-17.8
+17.4
diff --git a/bench/runtime/zero/bench/carry-on.runtime b/bench/runtime/zero/bench/carry-on.runtime
--- a/bench/runtime/zero/bench/carry-on.runtime
+++ b/bench/runtime/zero/bench/carry-on.runtime
@@ -1,1 +1,1 @@
-4.6
+4.8
diff --git a/bench/runtime/zero/bench/erroneous.runtime b/bench/runtime/zero/bench/erroneous.runtime
--- a/bench/runtime/zero/bench/erroneous.runtime
+++ b/bench/runtime/zero/bench/erroneous.runtime
@@ -1,1 +1,1 @@
-5.7
+5.6
diff --git a/bench/runtime/zero/bench/gps.runtime b/bench/runtime/zero/bench/gps.runtime
--- a/bench/runtime/zero/bench/gps.runtime
+++ b/bench/runtime/zero/bench/gps.runtime
@@ -1,1 +1,1 @@
-28.7
+27.9
diff --git a/bench/runtime/zero/bench/gps2.runtime b/bench/runtime/zero/bench/gps2.runtime
--- a/bench/runtime/zero/bench/gps2.runtime
+++ b/bench/runtime/zero/bench/gps2.runtime
@@ -1,1 +1,1 @@
-23.6
+22.8
diff --git a/bench/runtime/zero/bench/ill-hit.runtime b/bench/runtime/zero/bench/ill-hit.runtime
--- a/bench/runtime/zero/bench/ill-hit.runtime
+++ b/bench/runtime/zero/bench/ill-hit.runtime
@@ -1,1 +1,1 @@
-1.0
+1.1
diff --git a/bench/runtime/zero/bench/longshot.runtime b/bench/runtime/zero/bench/longshot.runtime
--- a/bench/runtime/zero/bench/longshot.runtime
+++ b/bench/runtime/zero/bench/longshot.runtime
@@ -1,1 +1,1 @@
-0.0
+0.1
diff --git a/bench/runtime/zero/bench/p30.runtime b/bench/runtime/zero/bench/p30.runtime
--- a/bench/runtime/zero/bench/p30.runtime
+++ b/bench/runtime/zero/bench/p30.runtime
@@ -1,1 +1,1 @@
-0.0
+0.1
diff --git a/bench/runtime/zero/bench/redundants.runtime b/bench/runtime/zero/bench/redundants.runtime
--- a/bench/runtime/zero/bench/redundants.runtime
+++ b/bench/runtime/zero/bench/redundants.runtime
@@ -1,1 +1,1 @@
-6.3
+6.2
diff --git a/bench/runtime/zero/bench/strategies.runtime b/bench/runtime/zero/bench/strategies.runtime
--- a/bench/runtime/zero/bench/strategies.runtime
+++ b/bench/runtime/zero/bench/strategies.runtime
@@ -1,1 +1,1 @@
-8.9
+9.1
diff --git a/bench/runtime/zero/bench/weird.runtime b/bench/runtime/zero/bench/weird.runtime
--- a/bench/runtime/zero/bench/weird.runtime
+++ b/bench/runtime/zero/bench/weird.runtime
@@ -1,1 +1,1 @@
-4.9
+4.7
diff --git a/bench/runtime/zero/eg/arith.runtime b/bench/runtime/zero/eg/arith.runtime
--- a/bench/runtime/zero/eg/arith.runtime
+++ b/bench/runtime/zero/eg/arith.runtime
@@ -1,1 +1,1 @@
-2.0
+1.9
diff --git a/bench/runtime/zero/eg/bits.runtime b/bench/runtime/zero/eg/bits.runtime
--- a/bench/runtime/zero/eg/bits.runtime
+++ b/bench/runtime/zero/eg/bits.runtime
@@ -1,1 +1,1 @@
-5.9
+5.8
diff --git a/bench/runtime/zero/eg/bools.runtime b/bench/runtime/zero/eg/bools.runtime
--- a/bench/runtime/zero/eg/bools.runtime
+++ b/bench/runtime/zero/eg/bools.runtime
@@ -1,1 +1,1 @@
-3.3
+3.2
diff --git a/bench/runtime/zero/eg/bst.runtime b/bench/runtime/zero/eg/bst.runtime
--- a/bench/runtime/zero/eg/bst.runtime
+++ b/bench/runtime/zero/eg/bst.runtime
@@ -1,1 +1,1 @@
-8.6
+8.5
diff --git a/bench/runtime/zero/eg/dupos.runtime b/bench/runtime/zero/eg/dupos.runtime
--- a/bench/runtime/zero/eg/dupos.runtime
+++ b/bench/runtime/zero/eg/dupos.runtime
@@ -1,1 +1,1 @@
-3.8
+3.6
diff --git a/bench/runtime/zero/eg/fibonacci.runtime b/bench/runtime/zero/eg/fibonacci.runtime
--- a/bench/runtime/zero/eg/fibonacci.runtime
+++ b/bench/runtime/zero/eg/fibonacci.runtime
@@ -1,1 +1,1 @@
-6.3
+6.2
diff --git a/bench/runtime/zero/eg/ints.runtime b/bench/runtime/zero/eg/ints.runtime
--- a/bench/runtime/zero/eg/ints.runtime
+++ b/bench/runtime/zero/eg/ints.runtime
@@ -1,1 +1,1 @@
-1.1
+1.0
diff --git a/bench/runtime/zero/eg/oddeven.runtime b/bench/runtime/zero/eg/oddeven.runtime
--- a/bench/runtime/zero/eg/oddeven.runtime
+++ b/bench/runtime/zero/eg/oddeven.runtime
@@ -1,1 +1,1 @@
-2.9
+3.0
diff --git a/bench/runtime/zero/eg/setelem.runtime b/bench/runtime/zero/eg/setelem.runtime
--- a/bench/runtime/zero/eg/setelem.runtime
+++ b/bench/runtime/zero/eg/setelem.runtime
@@ -1,1 +1,1 @@
-1.5
+1.4
diff --git a/bench/runtime/zero/eg/sort.runtime b/bench/runtime/zero/eg/sort.runtime
--- a/bench/runtime/zero/eg/sort.runtime
+++ b/bench/runtime/zero/eg/sort.runtime
@@ -1,1 +1,1 @@
-5.9
+6.0
diff --git a/bench/runtime/zero/eg/spec.runtime b/bench/runtime/zero/eg/spec.runtime
--- a/bench/runtime/zero/eg/spec.runtime
+++ b/bench/runtime/zero/eg/spec.runtime
@@ -1,1 +1,1 @@
-1.6
+1.5
diff --git a/bench/runtime/zero/eg/these.runtime b/bench/runtime/zero/eg/these.runtime
--- a/bench/runtime/zero/eg/these.runtime
+++ b/bench/runtime/zero/eg/these.runtime
@@ -1,1 +1,1 @@
-3.5
+3.4
diff --git a/bench/runtime/zero/eg/tree.runtime b/bench/runtime/zero/eg/tree.runtime
--- a/bench/runtime/zero/eg/tree.runtime
+++ b/bench/runtime/zero/eg/tree.runtime
@@ -1,1 +1,1 @@
-2.7
+2.6
diff --git a/bench/runtime/zero/eg/tuple.runtime b/bench/runtime/zero/eg/tuple.runtime
--- a/bench/runtime/zero/eg/tuple.runtime
+++ b/bench/runtime/zero/eg/tuple.runtime
@@ -1,1 +1,1 @@
-0.9
+1.4
diff --git a/bench/runtime/zero/versions b/bench/runtime/zero/versions
--- a/bench/runtime/zero/versions
+++ b/bench/runtime/zero/versions
@@ -1,4 +1,4 @@
-GHC 9.2.8
+GHC 9.4.8
 leancheck-1.0.2
 express-1.0.18
 speculate-0.4.20
diff --git a/bench/self.hs b/bench/self.hs
--- a/bench/self.hs
+++ b/bench/self.hs
@@ -6,19 +6,17 @@
 
 main :: IO ()
 main = do
-  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 -> [Prim] -> IO ()
-  cj  =  conjureWith args{maxSize=3,maxEquationSize=0}
+  conjure "?" ((+) :: Int -> Int -> Int)   ingredients
+  conjure "?" ((*) :: Int -> Int -> Int)   ingredients
+  conjure "i" ((+1) :: Int -> Int)         ingredients
+  conjure "d" ((subtract 1) :: Int -> Int) ingredients
 
-primitives :: [Prim]
-primitives =
-  [ pr (0::Int)
-  , pr (1::Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "*" ((*) :: Int -> Int -> Int)
+ingredients :: [Ingredient]
+ingredients =
+  [ con (0::Int)
+  , con (1::Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "*" ((*) :: Int -> Int -> Int)
+  , maxSize 3
+  , maxEquationSize 0
   ]
diff --git a/bench/self.txt b/bench/self.txt
--- a/bench/self.txt
+++ b/bench/self.txt
@@ -32,5 +32,5 @@
 -- 3 candidates of size 2
 -- 12 candidates of size 3
 -- tested 18 candidates
-cannot conjure
+d  =  undefined  -- search exhausted
 
diff --git a/bench/strategies.hs b/bench/strategies.hs
--- a/bench/strategies.hs
+++ b/bench/strategies.hs
@@ -11,16 +11,13 @@
 factorial 4  =  24
 
 
-mkStrategy :: String -> Args
-mkStrategy s  =  args
-  { rewriting         =  r
-  , requireDescent    =  d
-  , adHocRedundancy   =  a
-  , copyBindings      =  a -- previously c
-  , uniqueCandidates  =  u
---, carryOn  =  True
---, maxSize  =  10
-  }
+-- TODO: simplify and refactor
+mkStrategy :: String -> [Ingredient]
+mkStrategy s  =  [ dontRewrite | not r ]
+              ++ [ dontRequireDescent | not d ]
+              ++ [ omitAssortedPruning | not a ]
+              ++ [ dontCopyBindings | not a ]
+              ++ [ uniqueCandidates | u]
   where
   itob 0  =  False
   itob _  =  True
@@ -37,10 +34,10 @@
     "only typed"        -> [0,0,0,0]
     _                   -> error "unknown strategy"
 
-conjureStrategy :: Conjurable f => String -> String -> f -> [Prim] -> IO ()
-conjureStrategy name nm f prims  =  do
+conjureStrategy :: Conjurable f => String -> String -> f -> [Ingredient] -> IO ()
+conjureStrategy name nm f ingrs =  do
   putStrLn $ "-- strategy: " ++ name
-  conjureWith (mkStrategy name) nm f prims
+  conjure nm f $ ingrs ++ mkStrategy name
 
 strategies :: [String]
 strategies  =  
@@ -58,15 +55,15 @@
 main :: IO ()
 main  =  do
   sequence_
-    [ conjureStrategy s "factorial n" factorial primitives
+    [ conjureStrategy s "factorial n" factorial ingredients
     | s <- strategies
     ]
 
-primitives :: [Prim]
-primitives = 
-    [ pr (0::Int)
-    , pr (1::Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
+ingredients :: [Ingredient]
+ingredients = 
+    [ con (0::Int)
+    , con (1::Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
     ]
diff --git a/bench/terpret.hs b/bench/terpret.hs
--- a/bench/terpret.hs
+++ b/bench/terpret.hs
@@ -28,20 +28,20 @@
 t1c  =  do
   putStrLn "TerpreT benchmark #1: invert\n"
 
-  conjure "invert" t1p primitives123
+  conjure "invert" t1p ingredients123
 
--- the same primitives are used for TerpreT #1, #2 and #3
-primitives123 :: [Prim]
-primitives123  =
-  [ pr False
-  , pr True
-  , prim "not" not
-  , prim "&&" (&&)
-  , prim "||" (||)
-  , pr ([] :: [Bool])
-  , prim ":" ((:) :: Bool -> [Bool] -> [Bool])
---, prim "map" (map :: (Bool -> Bool) -> [Bool] -> [Bool])
-  , prif (undefined :: [Bool])
+-- the same ingredients are used for TerpreT #1, #2 and #3
+ingredients123 :: [Ingredient]
+ingredients123  =
+  [ con False
+  , con True
+  , fun "not" not
+  , fun "&&" (&&)
+  , fun "||" (||)
+  , con ([] :: [Bool])
+  , fun ":" ((:) :: Bool -> [Bool] -> [Bool])
+--, fun "map" (map :: (Bool -> Bool) -> [Bool] -> [Bool])
+  , iif (undefined :: [Bool])
   ]
 
 
@@ -58,7 +58,7 @@
 t2c  =  do
   putStrLn "TerpreT benchmark #2: prepend zero\n"
 
-  conjure "prependZero" t2p primitives123
+  conjure "prependZero" t2p ingredients123
 
 
 -- TerpreT #3 -- binary decrement --
@@ -83,7 +83,7 @@
 t3c  =  do
   putStrLn "TerpreT benchmark #3: binary decrement\n"
 
-  conjure "decrement" t3p primitives123
+  conjure "decrement" t3p ingredients123
 
 
 -- TerpreT #4 -- 2-bit controlled shift register --
@@ -108,14 +108,15 @@
 t4c  =  do
   putStrLn "TerpreT benchmark #4: controlled shift\n"
 
-  conjureWith args{target = 50400} "cshift" t4p1 $ primitives123 ++
-    [ prim ",," ((,,) :: Bool -> Bool -> Bool -> (Bool,Bool,Bool))
-    , prif (undefined :: (Bool,Bool,Bool))
+  conjure "cshift" t4p1 $ ingredients123 ++
+    [ fun ",," ((,,) :: Bool -> Bool -> Bool -> (Bool,Bool,Bool))
+    , iif (undefined :: (Bool,Bool,Bool))
+    , target 50400
     ]
 
-  conjure "cshift" t4p2 $ primitives123 ++
-    [ prim ",," ((,,) :: Bool -> Bool -> Bool -> (Bool,Bool,Bool))
-    , prif (undefined :: (Bool,Bool,Bool))
+  conjure "cshift" t4p2 $ ingredients123 ++
+    [ fun ",," ((,,) :: Bool -> Bool -> Bool -> (Bool,Bool,Bool))
+    , iif (undefined :: (Bool,Bool,Bool))
     ]
 
 
@@ -135,15 +136,15 @@
 t5c  =  do
   putStrLn "TerpreT benchmark #5: full adder\n"
 
-  -- using primitives123 below works, but increases the runtime to 18 seconds
+  -- using ingredients123 below works, but increases the runtime to 18 seconds
   -- let's leave it commented out so runtime is faster when running automated tests
-  -- BENCHMARK: uncomment primitives123
-  conjure "fadder" t5p $ -- primitives123 ++
-    [ prim "not" not
-    , prim "," ((,) :: Bool -> Bool -> (Bool,Bool))
-    , prim "==" ((==) :: Bool -> Bool -> Bool)
---  , prim "^^" ((/=) :: Bool -> Bool -> Bool) -- poor man's xor
-    , prif (undefined :: (Bool,Bool))
+  -- BENCHMARK: uncomment ingredients123
+  conjure "fadder" t5p $ -- ingredients123 ++
+    [ fun "not" not
+    , fun "," ((,) :: Bool -> Bool -> (Bool,Bool))
+    , fun "==" ((==) :: Bool -> Bool -> Bool)
+--  , fun "^^" ((/=) :: Bool -> Bool -> Bool) -- poor man's xor
+    , iif (undefined :: (Bool,Bool))
     ]
 -- the printed function is weird, but correct
 -- fadder p q r  =  if p == q then (p,r) else (r,not r)
@@ -160,11 +161,12 @@
 t6c :: IO ()
 t6c  =  do
   putStrLn "TerpreT benchmark #6: 2-bit adder\n"
-  conjureWith args{maxSize=6} "adder2" t6p $ primitives123 ++
-    [ prim ",," ((,,) :: Bool -> Bool -> Bool -> (Bool,Bool,Bool))
-    , prim "==" ((==) :: Bool -> Bool -> Bool)
-    , prim "^^" ((/=) :: Bool -> Bool -> Bool) -- poor man's xor
-    , prif (undefined :: (Bool,Bool,Bool))
+  conjure "adder2" t6p $ ingredients123 ++
+    [ fun ",," ((,,) :: Bool -> Bool -> Bool -> (Bool,Bool,Bool))
+    , fun "==" ((==) :: Bool -> Bool -> Bool)
+    , fun "^^" ((/=) :: Bool -> Bool -> Bool) -- poor man's xor
+    , iif (undefined :: (Bool,Bool,Bool))
+    , maxSize 6
     ]
 
 
@@ -186,16 +188,16 @@
   putStrLn "TerpreT benchmark #7: access\n"
   -- yes, one can implement index with index...
   conjure "`access`" t7p
-    [ prim "!!" ((!!) :: [A] -> Int -> A)
+    [ fun "!!" ((!!) :: [A] -> Int -> A)
     ]
 
   conjure "`access`" t7p
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , pr ([] :: [A])
-    , prim ":" ((:) :: A -> [A] -> [A])
-    , prim "-" ((-) :: Int -> Int -> Int)
-    , prim "undefined" (undefined :: A)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , con ([] :: [A])
+    , fun ":" ((:) :: A -> [A] -> [A])
+    , fun "-" ((-) :: Int -> Int -> Int)
+    , fun "undefined" (undefined :: A)
     ]
 
 
@@ -210,22 +212,22 @@
   putStrLn "TerpreT benchmark #8: decrement elements\n"
 
   conjure "decrelements" t8p
-    [ pr (1 :: Int)
-    , pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "-" ((-) :: Int -> Int -> Int)
-    , prim "map" (map :: (Int -> Int) -> [Int] -> [Int])
+    [ con (1 :: Int)
+    , con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "-" ((-) :: Int -> Int -> Int)
+    , fun "map" (map :: (Int -> Int) -> [Int] -> [Int])
     ]
   -- above, even though map is provided, Conjure cannot use it as it cannot
   -- introduce lambdas
 
   conjure "decrelements" t8p
-    [ pr (1 :: Int)
-    , pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "-" ((-) :: Int -> Int -> Int)
-    , prim "map" (map :: (Int -> Int) -> [Int] -> [Int])
-    , prim "subtract" (subtract :: Int -> Int -> Int)
+    [ con (1 :: Int)
+    , con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "-" ((-) :: Int -> Int -> Int)
+    , fun "map" (map :: (Int -> Int) -> [Int] -> [Int])
+    , fun "subtract" (subtract :: Int -> Int -> Int)
     ]
   -- now above, the story changes because of subtract, map is used
 
diff --git a/bench/terpret.txt b/bench/terpret.txt
--- a/bench/terpret.txt
+++ b/bench/terpret.txt
@@ -116,7 +116,7 @@
 -- 0 candidates of size 5
 -- 0 candidates of size 6
 -- tested 8 candidates
-cannot conjure
+adder2  =  undefined  -- search exhausted
 
 TerpreT benchmark #7: access
 
diff --git a/bench/unique.hs b/bench/unique.hs
--- a/bench/unique.hs
+++ b/bench/unique.hs
@@ -23,8 +23,8 @@
 -- * maximum candidate size (5 = few seconds, 7 = few minutes);
 -- * function name (for pretty-printing purposes);
 -- * proxy value to indicate the type of functions to generate;
--- * list of primitives, in Conjure-compatible form.
-printUniqueCandidates :: Conjurable f => Int -> String -> f -> [Prim] -> IO ()
+-- * list of ingredients, in Conjure-compatible form.
+printUniqueCandidates :: Conjurable f => Int -> String -> f -> [Ingredient] -> IO ()
 printUniqueCandidates n nm f ps  =  do
   putStrLn $ "Unique candidates for: " ++ nm ++ " :: " ++ show (typeOf f)
   putStrLn $ "  pruning with " ++ show nRules ++ "/" ++ show nREs ++ " rules"
@@ -46,7 +46,7 @@
   css            =  take n
                  $  discardT isRedundantByIntroduction -- additional pruning rule
                  $  css'
-  (css', thy, _, _) =  candidateDefnsC args nm f ps  -- Conjure uses this for listing candidates
+  (css', thy, _, _) =  candidateDefns nm f ps  -- Conjure uses this for listing candidates
   nRules         =  length (rules thy)
   nREs           =  length (equations thy) + nRules
   maxTests       =  60 -- a hardcoded value probably will not hurt in this simple benchmark
@@ -64,44 +64,44 @@
   let n = 5
 
   printUniqueCandidates (n+2) "foo" (undefined :: Int -> Int)
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
     ]
 
   printUniqueCandidates n "?" (undefined :: Int -> Int -> Int)
-    [ pr (0 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "dec" (subtract 1 :: Int -> Int)
+    [ con (0 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "dec" (subtract 1 :: Int -> Int)
     ]
 
   printUniqueCandidates (n+2) "goo" (undefined :: [Int] -> [Int])
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
     ]
 
   printUniqueCandidates n "??" (undefined :: [Int] -> [Int] -> [Int])
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
     ]
 
   printUniqueCandidates (n+2) "ton" (undefined :: Bool -> Bool)
-    [ pr False
-    , pr True
-    , prim "&&" (&&)
-    , prim "||" (||)
-    , prim "not" not
+    [ con False
+    , con True
+    , fun "&&" (&&)
+    , fun "||" (||)
+    , fun "not" not
     ]
 
   printUniqueCandidates n "&|" (undefined :: Bool -> Bool -> Bool)
-    [ pr False
-    , pr True
-    , prim "&&" (&&)
-    , prim "||" (||)
-    , prim "not" not
+    [ con False
+    , con True
+    , fun "&&" (&&)
+    , fun "||" (||)
+    , fun "not" not
     ]
diff --git a/bench/weird.hs b/bench/weird.hs
--- a/bench/weird.hs
+++ b/bench/weird.hs
@@ -21,24 +21,24 @@
 
 main :: IO ()
 main  =  do
-  conjure "^^^" (^^^) primitives
-  conjureWith args{usePatterns = False} "^^^" (^^^) primitives
+  conjure "^^^" (^^^)   ingredients
+  conjure "^^^" (^^^) $ ingredients ++ [singlePattern]
 
   -- This example is quite the degenerate case,
-  -- it takes a while to conjure even with just 2 primitives.
+  -- it takes a while to conjure even with just 2 ingredients.
   -- I am leaving it commented-out for now...
-  -- conjure "thirty" thirty [pr (0::Int), prim "+" ((+) :: Int -> Int -> Int)]
+  -- conjure "thirty" thirty [pr (0::Int), fun "+" ((+) :: Int -> Int -> Int)]
 
-primitives :: [Prim]
-primitives  =
-  [ pr (0::Int)
-  , pr (1::Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "*" ((*) :: Int -> Int -> Int)
-  , prim "==" ((==) :: Int -> Int -> Bool)
-  , prim "&&" (&&)
-  , prim "||" (||)
-  , prif (undefined :: Int)
+ingredients :: [Ingredient]
+ingredients  =
+  [ con (0::Int)
+  , con (1::Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "*" ((*) :: Int -> Int -> Int)
+  , fun "==" ((==) :: Int -> Int -> Bool)
+  , fun "&&" (&&)
+  , fun "||" (||)
+  , iif (undefined :: Int)
   -- guard does not play well with usePatterns = False yet
   ]
 
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -2,6 +2,25 @@
 ============================
 
 
+v0.7.0 (May 2025)
+-----------------
+
+* Several breaking API changes;
+* `Prim` is now `Ingredient`;
+* `pr` and `prim` are now `con` and `fun`;
+* `prif` is now `iif`;
+* `primOrdCaseFor` is now `ordcase`;
+* `Prim`, `pr`, `prim`, `prif`, `primOrdCaseFor` are deprecated;
+* `Args` and `args` were replaced by ingredient settings:
+  `maxTests`, `target`, `maxSize`, etc;
+* display `search exhausted` when a suitable candidate is not found
+  (instead of `cannot conjure`);
+* display warning when the specification cannot be reified;
+* lightly improve internal testing of `conjure`;
+* try to place recursive calls last in commutative operators
+  before showing a resulting function.
+
+
 v0.6.10 (February 2025)
 -----------------------
 
diff --git a/code-conjure.cabal b/code-conjure.cabal
--- a/code-conjure.cabal
+++ b/code-conjure.cabal
@@ -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.6.10
+version:             0.7.0
 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.6.10
+  tag:             v0.7.0
 
 library
   exposed-modules: Conjure
@@ -77,13 +77,14 @@
                  , Conjure.Conjurable.Derive
                  , Conjure.Engine
                  , Conjure.Expr
-                 , Conjure.Prim
+                 , Conjure.Ingredient
                  , Conjure.Utils
                  , Conjure.Defn
                  , Conjure.Defn.Redundancy
                  , Conjure.Defn.Test
                  , Conjure.Red
                  , Conjure.Reason
+                 , Conjure.Settings
   other-extensions: TemplateHaskell, CPP
   build-depends: base >= 4 && < 5
                , leancheck >= 1.0.0
@@ -136,6 +137,14 @@
 test-suite red
   type:                exitcode-stdio-1.0
   main-is:             red.hs
+  other-modules:       Test, Test.ListableExpr
+  hs-source-dirs:      test
+  build-depends:       base >= 4 && < 5, leancheck, express, speculate, code-conjure
+  default-language:    Haskell2010
+
+test-suite factorial
+  type:                exitcode-stdio-1.0
+  main-is:             factorial.hs
   other-modules:       Test, Test.ListableExpr
   hs-source-dirs:      test
   build-depends:       base >= 4 && < 5, leancheck, express, speculate, code-conjure
diff --git a/eg/arith.hs b/eg/arith.hs
--- a/eg/arith.hs
+++ b/eg/arith.hs
@@ -39,17 +39,17 @@
 
 main :: IO ()
 main = do
-  conjure "double" double primitives
-  conjure "triple" triple primitives
-  conjure "add"    add    primitives
-  conjure "square" square primitives
-  conjure "cube"   cube   primitives
-  conjure "tnpo"   tnpo   primitives
+  conjure "double" double ingredients
+  conjure "triple" triple ingredients
+  conjure "add"    add    ingredients
+  conjure "square" square ingredients
+  conjure "cube"   cube   ingredients
+  conjure "tnpo"   tnpo   ingredients
 
-primitives :: [Prim]
-primitives =
-  [ pr (0::Int)
-  , pr (1::Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "*" ((*) :: Int -> Int -> Int)
+ingredients :: [Ingredient]
+ingredients =
+  [ con (0::Int)
+  , con (1::Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "*" ((*) :: Int -> Int -> Int)
   ]
diff --git a/eg/bits.hs b/eg/bits.hs
--- a/eg/bits.hs
+++ b/eg/bits.hs
@@ -19,22 +19,22 @@
 main :: IO ()
 main  =  do
   conjure "bitsum" bitsum
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "halve" ((`div` 2) :: Int -> Int)
-    , prim "parity" ((`mod` 2) :: Int -> Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "halve" ((`div` 2) :: Int -> Int)
+    , fun "parity" ((`mod` 2) :: Int -> Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
     ]
   -- bitsum 0  =  0
   -- bitsum n  =  parity n + bitsum (halve n)
 
   conjure "bitsum" bitsum
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , pr (2 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "`div`" (div :: Int -> Int -> Int)
-    , prim "`mod`" (mod :: Int -> Int -> Int)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , con (2 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "`div`" (div :: Int -> Int -> Int)
+    , fun "`mod`" (mod :: Int -> Int -> Int)
     ]
   -- bitsum 0  =  0
   -- bitsum n  =  n `mod` 2 + bitsum (n `div` 2)
diff --git a/eg/bits.txt b/eg/bits.txt
--- a/eg/bits.txt
+++ b/eg/bits.txt
@@ -10,7 +10,7 @@
 -- 182 candidates of size 7
 -- tested 145 candidates
 bitsum 0  =  0
-bitsum x  =  bitsum (halve x) + parity x
+bitsum x  =  parity x + bitsum (halve x)
 
 bitsum :: Int -> Int
 -- testing 8 combinations of argument values
@@ -26,5 +26,5 @@
 -- 89215 candidates of size 9
 -- tested 10191 candidates
 bitsum 0  =  0
-bitsum x  =  bitsum (x `div` 2) + x `mod` 2
+bitsum x  =  x `mod` 2 + bitsum (x `div` 2)
 
diff --git a/eg/bools.hs b/eg/bools.hs
--- a/eg/bools.hs
+++ b/eg/bools.hs
@@ -16,23 +16,23 @@
 
 main :: IO ()
 main = do
-  conjure "and" (and' :: [Bool] -> Bool) primitives
-  conjure "or"  (or'  :: [Bool] -> Bool) primitives
+  conjure "and" (and' :: [Bool] -> Bool) ingredients
+  conjure "or"  (or'  :: [Bool] -> Bool) ingredients
 
   -- conjure can use fold as well
-  conjure "and" (and' :: [Bool] -> Bool) primitivesWithFold
-  conjure "or"  (or'  :: [Bool] -> Bool) primitivesWithFold
+  conjure "and" (and' :: [Bool] -> Bool) ingredientsWithFold
+  conjure "or"  (or'  :: [Bool] -> Bool) ingredientsWithFold
 
-primitives :: [Prim]
-primitives =
-  [ pr False
-  , pr True
-  , prim "not" not
-  , prim "||" (||)
-  , prim "&&" (&&)
+ingredients :: [Ingredient]
+ingredients =
+  [ con False
+  , con True
+  , fun "not" not
+  , fun "||" (||)
+  , fun "&&" (&&)
   ]
 
-primitivesWithFold :: [Prim]
-primitivesWithFold  =
-    prim "foldr" (foldr :: (Bool -> Bool -> Bool) -> Bool -> [Bool] -> Bool)
-  : primitives
+ingredientsWithFold :: [Ingredient]
+ingredientsWithFold  =
+    fun "foldr" (foldr :: (Bool -> Bool -> Bool) -> Bool -> [Bool] -> Bool)
+  : ingredients
diff --git a/eg/bst.hs b/eg/bst.hs
--- a/eg/bst.hs
+++ b/eg/bst.hs
@@ -123,74 +123,81 @@
 main :: IO ()
 main = do
   conjure "mem" mem
-    [ pr False
-    , prim "||" (||)
-    , prim "==" ((==) :: Int -> Int -> Bool)
-    , prim "<" ((<) :: Int -> Int -> Bool)
+    [ con False
+    , fun "||" (||)
+    , fun "==" ((==) :: Int -> Int -> Bool)
+    , fun "<" ((<) :: Int -> Int -> Bool)
     , guard
     ]
 
   conjure "mem" mem
-    [ pr False
-    , pr True
-    , prim "`compare`" (compare :: Int -> Int -> Ordering)
-    , primOrdCaseFor (undefined :: Bool)
+    [ con False
+    , con True
+    , fun "`compare`" (compare :: Int -> Int -> Ordering)
+    , ordcase (undefined :: Bool)
     ]
 
   -- simply out of reach performance-wise (reaching 16 but need size 22)
-  conjureWithMaxSize 12 "insert" insert
-    [ pr Leaf
-    , prim "Node" Node
-    , prim "unit" unit
-    , prim "`compare`" (compare :: Int -> Int -> Ordering)
-    , primOrdCaseFor (undefined :: Tree)
+  conjure "insert" insert
+    [ con Leaf
+    , fun "Node" Node
+    , fun "unit" unit
+    , fun "`compare`" (compare :: Int -> Int -> Ordering)
+    , ordcase (undefined :: Tree)
+    , maxSize 12
     ]
 
   -- reachable in 15s, candidate #32878 at size 14.
   -- increase target to 50400 to reach...
-  conjureFromSpecWith args{target=5040} "before" beforeSpec
-    [ pr Leaf
-    , prim "Node" Node
-    , prim "==" ((==) :: Int -> Int -> Bool)
-    , prim "<" ((<) :: Int -> Int -> Bool)
+  conjureFromSpec "before" beforeSpec
+    [ con Leaf
+    , fun "Node" Node
+    , fun "==" ((==) :: Int -> Int -> Bool)
+    , fun "<" ((<) :: Int -> Int -> Bool)
     , guard
+    , target 5040
     ]
 
   -- reachable in 14s, candidate #32747 at size 14.
   -- increase target to 50400 to reach...
-  conjureFromSpecWith args{target=5040} "beyond" beyondSpec
-    [ pr Leaf
-    , prim "Node" Node
-    , prim "==" ((==) :: Int -> Int -> Bool)
-    , prim "<=" ((<) :: Int -> Int -> Bool)
+  conjureFromSpec "beyond" beyondSpec
+    [ con Leaf
+    , fun "Node" Node
+    , fun "==" ((==) :: Int -> Int -> Bool)
+    , fun "<=" ((<) :: Int -> Int -> Bool)
     , guard
+    , target 5040
     ]
 
   -- with 15, this reaches the solution, using 12 for shorter runtime
   -- using maxEquationSize = 7 reduces runtime from 13s to 11s
-  conjureFromSpecWith args{maxSize = 12, maxEquationSize = 7} "before" beforeSpec
-    [ pr Leaf
-    , prim "Node" Node
-    , prim "`compare`" (compare :: Int -> Int -> Ordering)
-    , primOrdCaseFor (undefined :: Tree)
+  conjureFromSpec "before" beforeSpec
+    [ con Leaf
+    , fun "Node" Node
+    , fun "`compare`" (compare :: Int -> Int -> Ordering)
+    , ordcase (undefined :: Tree)
+    , maxSize 12
+    , maxEquationSize 7
     ]
 
   -- with 15, this reaches the solution, using 12 for shorter runtime
   -- using maxEquationSize = 7 reduces runtime from 13s to 11s
-  conjureFromSpecWith args{maxSize = 12, maxEquationSize = 7} "beyond" beyondSpec
-    [ pr Leaf
-    , prim "Node" Node
-    , prim "`compare`" (compare :: Int -> Int -> Ordering)
-    , primOrdCaseFor (undefined :: Tree)
+  conjureFromSpec "beyond" beyondSpec
+    [ con Leaf
+    , fun "Node" Node
+    , fun "`compare`" (compare :: Int -> Int -> Ordering)
+    , ordcase (undefined :: Tree)
+    , maxSize 12
+    , maxEquationSize 7
     ]
 
   -- reachable in 55s, candidate #173109 at size 13.
-  -- increase to 554400 to reach
-  conjureWith args{target=5544} "union" union
-    [ pr Leaf
-    , prim "Node" Node
-    , prim "before" before
-    , prim "beyond" beyond
+  conjure "union" union
+    [ con Leaf
+    , fun "Node" Node
+    , fun "before" before
+    , fun "beyond" beyond
+    , target 5544 -- increase to 554400 to reach
     ]
   -- maybe with invariant following test data there will be more pruning
   -- properties?
diff --git a/eg/bst.txt b/eg/bst.txt
--- a/eg/bst.txt
+++ b/eg/bst.txt
@@ -15,7 +15,7 @@
 -- 96 candidates of size 12
 -- tested 362 candidates
 mem x Leaf  =  False
-mem x (Node t1 y t2)  =  mem x t1 || (mem x t2 || x == y)
+mem x (Node t1 y t2)  =  mem x t1 || (x == y || mem x t2)
 
 mem :: Int -> Tree -> Bool
 -- testing 360 combinations of argument values
@@ -55,7 +55,7 @@
 -- 0 candidates of size 11
 -- 32 candidates of size 12
 -- tested 264 candidates
-cannot conjure
+insert  =  undefined  -- search exhausted
 
 before :: Int -> Tree -> Tree
 -- pruning with 5/6 rules
@@ -71,7 +71,7 @@
 -- 1342 candidates of size 10
 -- 3543 candidates of size 11
 -- tested 5343 candidates
-cannot conjure
+before  =  undefined  -- search exhausted
 
 beyond :: Int -> Tree -> Tree
 -- pruning with 5/6 rules
@@ -87,7 +87,7 @@
 -- 1342 candidates of size 10
 -- 3543 candidates of size 11
 -- tested 5343 candidates
-cannot conjure
+beyond  =  undefined  -- search exhausted
 
 before :: Int -> Tree -> Tree
 -- pruning with 2/4 rules
@@ -104,7 +104,7 @@
 -- 5103 candidates of size 11
 -- 1472 candidates of size 12
 -- tested 8207 candidates
-cannot conjure
+before  =  undefined  -- search exhausted
 
 beyond :: Int -> Tree -> Tree
 -- pruning with 2/4 rules
@@ -121,7 +121,7 @@
 -- 5103 candidates of size 11
 -- 1472 candidates of size 12
 -- tested 8207 candidates
-cannot conjure
+beyond  =  undefined  -- search exhausted
 
 union :: Tree -> Tree -> Tree
 -- testing 360 combinations of argument values
@@ -137,5 +137,5 @@
 -- 3018 candidates of size 9
 -- 8098 candidates of size 10
 -- tested 11531 candidates
-cannot conjure
+union  =  undefined  -- search exhausted
 
diff --git a/eg/colin/IntFuns.hs b/eg/colin/IntFuns.hs
--- a/eg/colin/IntFuns.hs
+++ b/eg/colin/IntFuns.hs
@@ -12,12 +12,12 @@
 -- hoping for something like
 -- tri x = if x==1 then 1 else x + tri (dec x)
 
-triPrimitives :: [Prim]
-triPrimitives =
-  [ prim "==" ((==) :: Int -> Int -> Bool)
-  , pr (1::Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "dec" ((\x -> x-1) :: Int -> Int)
+triIngredients :: [Ingredient]
+triIngredients =
+  [ fun "==" ((==) :: Int -> Int -> Bool)
+  , con (1::Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "dec" ((\x -> x-1) :: Int -> Int)
   ]
 
 -- looking through 3039 candidates, 25% match, 1/4 assignments
@@ -34,13 +34,13 @@
 -- hoping for something like
 -- fib x = if x <= 1 then 1 else fib (dec (dec x)) + fib (dec x)
 --         1  2 3  4      5      6    7    8   9   10 11  12  13
-fibPrimitives :: [Prim]
-fibPrimitives =
-  [ prim "<=" ((<=) :: Int -> Int -> Bool)
-  , pr (0::Int)
-  , pr (1::Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "dec" ((\x -> x-1) :: Int -> Int)
+fibIngredients :: [Ingredient]
+fibIngredients =
+  [ fun "<=" ((<=) :: Int -> Int -> Bool)
+  , con (0::Int)
+  , con (1::Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "dec" ((\x -> x-1) :: Int -> Int)
   ]
 
 -- looking through 23418 candidates
@@ -54,10 +54,10 @@
 
 -- hoping for
 -- exp x = product (replicate x x)
-expPrimitives :: [Prim]
-expPrimitives =
-  [ prim "replicate" (replicate :: Int -> Int -> [Int])
-  , prim "product" (product :: [Int] -> Int)
+expIngredients :: [Ingredient]
+expIngredients =
+  [ fun "replicate" (replicate :: Int -> Int -> [Int])
+  , fun "product" (product :: [Int] -> Int)
   ]
 
 -- looking through 18 candidates
@@ -74,12 +74,12 @@
 
 -- hoping for something like
 -- pri p = factors p == list2 1 p
-priPrimitives :: [Prim]
-priPrimitives =
-  [ prim "==" ((==) :: [Int] -> [Int] -> Bool)
-  , prim "factors" ((\n -> filter (\k -> n `mod` k == 0) [1..n]) :: Int -> [Int])
-  , prim "list2" ((\i j -> [i,j]) :: Int -> Int -> [Int])
-  , pr (1 :: Int)
+priIngredients :: [Ingredient]
+priIngredients =
+  [ 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)
   ]
 
 -- looking through 38 candidates, 100% match, 7/7 assignments
@@ -88,8 +88,8 @@
 
 main :: IO ()
 main = do
-  conjureWithMaxSize 10 "tri" tri triPrimitives
-  conjureWith args{maxSize=13} "fib" fib fibPrimitives
-  conjure "exp" exp expPrimitives
-  conjure "pri" pri priPrimitives
+  conjureWithMaxSize 10 "tri" tri triIngredients
+  conjureWith args{maxSize=13} "fib" fib fibIngredients
+  conjure "exp" exp expIngredients
+  conjure "pri" pri priIngredients
 
diff --git a/eg/colin/ListFuns.hs b/eg/colin/ListFuns.hs
--- a/eg/colin/ListFuns.hs
+++ b/eg/colin/ListFuns.hs
@@ -11,10 +11,10 @@
 -- sum []      =  0
 -- sum (x:xs)  =  x + sum xs
 
-sumBackground :: [Prim]
+sumBackground :: [Ingredient]
 sumBackground =
-  [ pr (0::Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
+  [ con (0::Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
   ]
 
 app :: [Int] -> [Int] -> [Int]
@@ -26,9 +26,9 @@
 -- app []     ys  =  ys
 -- app (x:xs) ys  =  x : app xs ys
 
-appBackground :: [Prim]
+appBackground :: [Ingredient]
 appBackground =
-  [ prim ":" ((:) :: Int -> [Int] -> [Int])  
+  [ fun ":" ((:) :: Int -> [Int] -> [Int])  
   ]
 
 mem :: Int -> [Int] -> Bool
@@ -42,12 +42,12 @@
 -- mem x []      =  False
 -- mem x (y:ys)  =  x == y || mem x ys
 
-memBackground :: [Prim]
+memBackground :: [Ingredient]
 memBackground =
-  [ pr False
-  , prim "==" ((==) :: Int -> Int -> Bool)
-  , prim "&&" ((&&) :: Bool -> Bool -> Bool)
-  , prim "||" ((||) :: Bool -> Bool -> Bool)
+  [ con False
+  , fun "==" ((==) :: Int -> Int -> Bool)
+  , fun "&&" ((&&) :: Bool -> Bool -> Bool)
+  , fun "||" ((||) :: Bool -> Bool -> Bool)
   ]
 
 sub :: [Int] -> [Int] -> Bool
@@ -67,13 +67,13 @@
 -- sub _      []      =  False
 -- sub (x:xs) (y:ys)  =  if x == y then sub xs ys else sub (x:xs) ys
 
-subBackground :: [Prim]
+subBackground :: [Ingredient]
 subBackground  =
-  [ pr True
-  , pr False
-  , prim ":" ((:) :: Int -> [Int] -> [Int])
-  , prim "==" ((==) :: Int -> Int -> Bool)
-  , prif (undefined :: Bool)
+  [ con True
+  , con False
+  , fun ":" ((:) :: Int -> [Int] -> [Int])
+  , fun "==" ((==) :: Int -> Int -> Bool)
+  , iif (undefined :: Bool)
   ]
 
 set :: [Int] -> Bool
@@ -90,11 +90,11 @@
 -- set []      =  True
 -- set (x:xs)  =  not (elem x xs) && set xs
 
-setBackground :: [Prim]
+setBackground :: [Ingredient]
 setBackground =
-  [ prim "not" (not :: Bool -> Bool)
-  , prim "&&" ((&&) :: Bool -> Bool -> Bool)
-  , prim "elem" (elem :: Int -> [Int] -> Bool)
+  [ fun "not" (not :: Bool -> Bool)
+  , fun "&&" ((&&) :: Bool -> Bool -> Bool)
+  , fun "elem" (elem :: Int -> [Int] -> Bool)
   ]
 
 take :: Int -> [A] -> [A]
@@ -110,13 +110,13 @@
 -- take x []      =  []
 -- take x (y:ys)  =  y : take (x-1) ys
 
-takeBackground :: [Prim]
+takeBackground :: [Ingredient]
 takeBackground  =
-  [ pr (0 :: Int)
-  , pr (1 :: Int)
-  , pr ([] :: [A])
-  , prim "-" ((-) :: Int -> Int -> Int)
-  , prim ":" ((:) :: A -> [A] -> [A])
+  [ con (0 :: Int)
+  , con (1 :: Int)
+  , con ([] :: [A])
+  , fun "-" ((-) :: Int -> Int -> Int)
+  , fun ":" ((:) :: A -> [A] -> [A])
   ]
 
 drop :: Int -> [A] -> [A]
@@ -132,12 +132,12 @@
 -- drop x []  =  []
 -- drop x (y:ys)  =  drop (x-1) ys
 
-dropBackground :: [Prim]
+dropBackground :: [Ingredient]
 dropBackground  =
-  [ pr (0 :: Int)
-  , pr (1 :: Int)
-  , pr ([] :: [A])
-  , prim "-" ((-) :: Int -> Int -> Int)
+  [ con (0 :: Int)
+  , con (1 :: Int)
+  , con ([] :: [A])
+  , fun "-" ((-) :: Int -> Int -> Int)
   ]
 
 ord :: [Int] -> Bool
@@ -153,14 +153,14 @@
 -- ord [x]  =  True
 -- ord (x:y:ys)  =  x <= y && ord (y:ys)
 
-ordBackground :: [Prim]
+ordBackground :: [Ingredient]
 ordBackground  =
-  [ pr True
-  , prim "null" (null :: [Int] -> Bool)
-  , prim "head" (head :: [Int] -> Int)
-  , prim "<=" ((<=) :: Int -> Int -> Bool)
-  , prim "&&" (&&)
-  , prim "||" (||)
+  [ con True
+  , fun "null" (null :: [Int] -> Bool)
+  , fun "head" (head :: [Int] -> Int)
+  , fun "<=" ((<=) :: Int -> Int -> Bool)
+  , fun "&&" (&&)
+  , fun "||" (||)
   ]
 
 merge :: [Int] -> [Int] -> [Int]
@@ -176,12 +176,12 @@
                         then x : merge xs (y:ys)
                         else y : merge (x:xs) ys
 
-mergeBackground :: [Prim]
+mergeBackground :: [Ingredient]
 mergeBackground  =
-  [ prim "<=" ((<=) :: Int -> Int -> Bool)
-  , pr ([] :: [Int])
-  , prim ":" ((:) :: Int -> [Int] -> [Int])
-  , prif (undefined :: [Int])
+  [ fun "<=" ((<=) :: Int -> Int -> Bool)
+  , con ([] :: [Int])
+  , fun ":" ((:) :: Int -> [Int] -> [Int])
+  , iif (undefined :: [Int])
   ]
 
 zip :: [A] -> [B] -> [(A,B)]
@@ -195,11 +195,11 @@
 -- zip (x:xs) []      =  []
 -- zip (x:xs) (y:ys)  =  (x,y) : zip xs ys
 
-zipBackground :: [Prim]
+zipBackground :: [Ingredient]
 zipBackground  =
-  [ pr ([] :: [(A,B)])
-  , prim "(,)" ((,) :: A -> B -> (A,B))
-  , prim ":" ((:) :: (A,B) -> [(A,B)] -> [(A,B)])
+  [ con ([] :: [(A,B)])
+  , fun "(,)" ((,) :: A -> B -> (A,B))
+  , fun ":" ((:) :: (A,B) -> [(A,B)] -> [(A,B)])
   ]
 
 assocs :: Int -> [(Int,A)] -> [A]
@@ -212,14 +212,14 @@
 -- assocs _ []      =  []
 -- assocs n (x:xs)  =  if fst x == n then snd x : assocs n xs else assocs n xs
 
-assocsBackground :: [Prim]
+assocsBackground :: [Ingredient]
 assocsBackground  =
-  [ pr ([] :: [A])
-  , prim "==" ((==) :: Int -> Int -> Bool)
-  , prim ":" ((:) :: A -> [A] -> [A])
-  , prim "fst" (fst :: (Int,A) -> Int)
-  , prim "snd" (snd :: (Int,A) -> A)
-  , prif (undefined :: [A])
+  [ con ([] :: [A])
+  , fun "==" ((==) :: Int -> Int -> Bool)
+  , fun ":" ((:) :: A -> [A] -> [A])
+  , fun "fst" (fst :: (Int,A) -> Int)
+  , fun "snd" (snd :: (Int,A) -> A)
+  , iif (undefined :: [A])
   ]
 
 main :: IO ()
diff --git a/eg/count.hs b/eg/count.hs
--- a/eg/count.hs
+++ b/eg/count.hs
@@ -30,27 +30,27 @@
   -- count x xs  =  length (filter (== x) xs)
   --                1       2       3  4  5
   conjure "count" count'
-    [ prim "length" (length :: [A] -> Int)
-    , prim "filter" (filter :: (A -> Bool) -> [A] -> [A])
-    , prim "==" ((==) :: A -> A -> Bool)
+    [ fun "length" (length :: [A] -> Int)
+    , fun "filter" (filter :: (A -> Bool) -> [A] -> [A])
+    , fun "==" ((==) :: A -> A -> Bool)
     ]
 
   -- count x []  =  0
   -- count x (y:xs)  =  count x xs + (if x == y then 1 else 0)
   conjure "count" count'
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "==" ((==) :: A -> A -> Bool)
-    , prif (undefined :: Int)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "==" ((==) :: A -> A -> Bool)
+    , iif (undefined :: Int)
     ]
 
   -- 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'
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "==" ((==) :: A -> A -> Bool)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "==" ((==) :: A -> A -> Bool)
     , guard
     ]
diff --git a/eg/count.txt b/eg/count.txt
--- a/eg/count.txt
+++ b/eg/count.txt
@@ -25,7 +25,7 @@
 -- 44 candidates of size 11
 -- tested 65 candidates
 count x []  =  0
-count x (y:xs)  =  count x xs + (if x == y then 1 else 0)
+count x (y:xs)  =  (if x == y then 1 else 0) + count x xs
 
 count :: A -> [A] -> Int
 -- testing 13 combinations of argument values
@@ -46,6 +46,6 @@
 -- tested 127 candidates
 count x []  =  0
 count x (y:xs)
-  | x == y  =  count x xs + 1
+  | x == y  =  1 + count x xs
   | otherwise  =  count x xs
 
diff --git a/eg/dupos.hs b/eg/dupos.hs
--- a/eg/dupos.hs
+++ b/eg/dupos.hs
@@ -53,32 +53,32 @@
   --                       else duplicates xs                              -- 17
   -- within reach performance wise.
   conjure "duplicates" duplicates'
-    [ pr ([] :: [Int])
-    , prim "not" not
-    , prim "&&" (&&)
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "elem" (elem :: Int -> [Int] -> Bool)
+    [ con ([] :: [Int])
+    , fun "not" not
+    , fun "&&" (&&)
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "elem" (elem :: Int -> [Int] -> Bool)
     , guard
     ]
 
   conjureFromSpec "duplicates" duplicatesSpec
-    [ pr ([] :: [Int])
-    , prim "not" not
-    , prim "&&" (&&)
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "elem" (elem :: Int -> [Int] -> Bool)
+    [ con ([] :: [Int])
+    , fun "not" not
+    , fun "&&" (&&)
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "elem" (elem :: Int -> [Int] -> Bool)
     , guard
     ]
 
   conjure "positionsFrom" positionsFrom'
-    [ pr ([] :: [Int])
-    , pr (1 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "==" ((==) :: A -> A -> Bool)
+    [ con ([] :: [Int])
+    , con (1 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "==" ((==) :: A -> A -> Bool)
 
---  , prif (undefined :: [Int])
+--  , iif (undefined :: [Int])
     -- cheat codes:
-    , prim "id" (id :: [Int] -> [Int])
-    , prif (undefined :: [Int] -> [Int])
+    , fun "id" (id :: [Int] -> [Int])
+    , iif (undefined :: [Int] -> [Int])
     ]
diff --git a/eg/either.hs b/eg/either.hs
--- a/eg/either.hs
+++ b/eg/either.hs
@@ -47,21 +47,21 @@
 
 main :: IO ()
 main = do
-  conjure "isLeft" isLeft' primitives
-  conjure "isRight" isRight' primitives
-  conjure "fromLeft" fromLeft' primitives
-  conjure "fromLeft" fromRight' primitives
-  conjureFromSpec "either" eitherSpec primitives
-  conjure "lefts" lefts' primitives
+  conjure "isLeft" isLeft' ingredients
+  conjure "isRight" isRight' ingredients
+  conjure "fromLeft" fromLeft' ingredients
+  conjure "fromLeft" fromRight' ingredients
+  conjureFromSpec "either" eitherSpec ingredients
+  conjure "lefts" lefts' ingredients
 
-primitives :: [Prim]
-primitives  =
-  [ prim "Left"  (Left :: A -> Either A A)
-  , prim "Right" (Right :: A -> Either A A)
+ingredients :: [Ingredient]
+ingredients  =
+  [ fun "Left"  (Left :: A -> Either A A)
+  , fun "Right" (Right :: A -> Either A A)
 
-  , pr False
-  , pr True
+  , con False
+  , con True
 
-  , pr ([] :: [A])
-  , prim ":" ((:) :: A -> [A] -> [A])
+  , con ([] :: [A])
+  , fun ":" ((:) :: A -> [A] -> [A])
   ]
diff --git a/eg/either.txt b/eg/either.txt
--- a/eg/either.txt
+++ b/eg/either.txt
@@ -50,5 +50,5 @@
 -- 1 candidates of size 1
 -- 0 candidates of size 2
 -- tested 1 candidates
-cannot conjure
+lefts  =  undefined  -- search exhausted
 
diff --git a/eg/factorial.hs b/eg/factorial.hs
--- a/eg/factorial.hs
+++ b/eg/factorial.hs
@@ -15,11 +15,11 @@
 main  =  do
   -- explicit recursion
   conjure "factorial n" factorial
-    [ pr (0::Int)
-    , pr (1::Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
+    [ con (0::Int)
+    , con (1::Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
     ]
   -- should produce:
   -- factorial 0  =  1
@@ -27,13 +27,13 @@
 
   -- using foldr and enumFromTo
   conjure "factorial n" factorial
-    [ pr (0::Int)
-    , pr (1::Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
-    , prim ".." (enumFromTo :: Int -> Int -> [Int])
-    , prim "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
+    [ con (0::Int)
+    , con (1::Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
+    , fun ".." (enumFromTo :: Int -> Int -> [Int])
+    , fun "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
     ]
   -- should produce:
   -- factorial x  =  foldr (*) 1 [1..x]
diff --git a/eg/fib01.hs b/eg/fib01.hs
--- a/eg/fib01.hs
+++ b/eg/fib01.hs
@@ -30,20 +30,26 @@
 
   -- Found!  It takes about 12 seconds to run with maxSize=8
   -- running with maxSize = 5 for faster runtime
-  conjureWith args{maxSize=5, maxConstantSize=1} "fib01" fib01
-    [ pr (0::Int)
-    , prim "dec" (subtract 1 :: Int -> Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
+  conjure "fib01" fib01
+    [ con (0::Int)
+    , fun "dec" (subtract 1 :: Int -> Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , maxSize 5
+    , maxConstantSize 1
     ]
 
   -- It takes about 27 seconds to run with maxSize=12
   -- running with maxSize = 9 for faster runtime
-  conjureWith args{usePatterns = False, maxSize = 1, maxConstantSize=1} "fib01" fib01
-    [ pr (0::Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "dec" (subtract 1 :: Int -> Int)
-    , prim "<=" ((<=) :: Int -> Int -> Bool)
-    , prif (undefined :: Int)
+  conjure "fib01" fib01
+    [ con (0::Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "dec" (subtract 1 :: Int -> Int)
+    , fun "<=" ((<=) :: Int -> Int -> Bool)
+    , iif (undefined :: Int)
+
+    , singlePattern
+    , maxSize 1
+    , maxConstantSize 1
     ]
   -- expected function:
   -- fib01 x y z  =  if z <= 0                     -- 4
diff --git a/eg/fib01.txt b/eg/fib01.txt
--- a/eg/fib01.txt
+++ b/eg/fib01.txt
@@ -7,12 +7,12 @@
 -- 111 candidates of size 4
 -- 255 candidates of size 5
 -- tested 422 candidates
-cannot conjure
+fib01  =  undefined  -- search exhausted
 
 fib01 :: Int -> Int -> Int -> Int
 -- testing 8 combinations of argument values
 -- pruning with 21/41 rules
 -- 4 candidates of size 1
 -- tested 4 candidates
-cannot conjure
+fib01  =  undefined  -- search exhausted
 
diff --git a/eg/fibonacci.hs b/eg/fibonacci.hs
--- a/eg/fibonacci.hs
+++ b/eg/fibonacci.hs
@@ -16,11 +16,11 @@
 main :: IO ()
 main  =  do
   conjure "fibonacci n" fibonacci
-    [ pr (0::Int)
-    , pr (1::Int)
-    , pr (2::Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
+    [ con (0::Int)
+    , con (1::Int)
+    , con (2::Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
     ]
 -- expected function:
 -- fibonacci 0  =  1
diff --git a/eg/gcd.hs b/eg/gcd.hs
--- a/eg/gcd.hs
+++ b/eg/gcd.hs
@@ -19,8 +19,8 @@
 
 main :: IO ()
 main = conjure "gcd a b" gcd'
-  [ pr (0::Int)
-  , prim "`mod`" (mod :: Int -> Int -> Int)
+  [ con (0::Int)
+  , fun "`mod`" (mod :: Int -> Int -> Int)
   ]
   -- desired function:
   -- gcd x 0  =  x
diff --git a/eg/higher.hs b/eg/higher.hs
--- a/eg/higher.hs
+++ b/eg/higher.hs
@@ -37,17 +37,17 @@
 
 main :: IO ()
 main = do
-  conjureFromSpec "$"      appSpec     primitives
-  conjureFromSpec "."      composeSpec primitives
-  conjureFromSpec "flip"   flipSpec    primitives
-  conjureFromSpec "map"    mapSpec     primitives
-  conjureFromSpec "fold"   foldSpec    primitives
-  conjureFromSpec "filter" filterSpec  primitives
+  conjureFromSpec "$"      appSpec     ingredients
+  conjureFromSpec "."      composeSpec ingredients
+  conjureFromSpec "flip"   flipSpec    ingredients
+  conjureFromSpec "map"    mapSpec     ingredients
+  conjureFromSpec "fold"   foldSpec    ingredients
+  conjureFromSpec "filter" filterSpec  ingredients
 
 
-primitives :: [Prim]
-primitives  =
-  [ pr ([] :: [Int])
-  , prim ":" ((:) :: Int -> [Int] -> [Int])
+ingredients :: [Ingredient]
+ingredients  =
+  [ con ([] :: [Int])
+  , fun ":" ((:) :: Int -> [Int] -> [Int])
   , guard
   ]
diff --git a/eg/id.hs b/eg/id.hs
--- a/eg/id.hs
+++ b/eg/id.hs
@@ -6,7 +6,7 @@
 
 main :: IO ()
 main = do
-  -- conjure needs no primitives
+  -- conjure needs no ingredients
   -- to figure out the implementation of id and const
   conjure "id"    (id :: Int -> Int)           []
   conjure "const" (const :: Int -> Int -> Int) []
diff --git a/eg/ints.hs b/eg/ints.hs
--- a/eg/ints.hs
+++ b/eg/ints.hs
@@ -26,43 +26,43 @@
 main :: IO ()
 main = do
   conjure "second"  (second :: [Int] -> Int)
-    [ prim "null" (null :: [Int] -> Bool)
-    , prim "head" (head :: [Int] -> Int)
-    , prim "tail" (tail :: [Int] -> [Int])
+    [ fun "null" (null :: [Int] -> Bool)
+    , fun "head" (head :: [Int] -> Int)
+    , fun "tail" (tail :: [Int] -> [Int])
     ]
 
   conjure "third"   (third :: [Int] -> Int)
-    [ prim "null" (null :: [Int] -> Bool)
-    , prim "head" (head :: [Int] -> Int)
-    , prim "tail" (tail :: [Int] -> [Int])
+    [ fun "null" (null :: [Int] -> Bool)
+    , fun "head" (head :: [Int] -> Int)
+    , fun "tail" (tail :: [Int] -> [Int])
     ]
 
   conjure "sum"     (sum' :: [Int] -> Int)
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
     ]
 
   conjure "product" (product' :: [Int] -> Int)
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
     ]
 
-  conjure "sum"     (sum' :: [Int] -> Int) primitivesWithFold
-  conjure "product" (product' :: [Int] -> Int) primitivesWithFold
+  conjure "sum"     (sum' :: [Int] -> Int) ingredientsWithFold
+  conjure "product" (product' :: [Int] -> Int) ingredientsWithFold
 
-primitives :: [Prim]
-primitives =
-  [ pr (0 :: Int)
-  , pr (1 :: Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "*" ((*) :: Int -> Int -> Int)
+ingredients :: [Ingredient]
+ingredients =
+  [ con (0 :: Int)
+  , con (1 :: Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "*" ((*) :: Int -> Int -> Int)
   ]
 
-primitivesWithFold :: [Prim]
-primitivesWithFold  =
-    prim "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
-  : primitives
+ingredientsWithFold :: [Ingredient]
+ingredientsWithFold  =
+    fun "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
+  : ingredients
diff --git a/eg/list.hs b/eg/list.hs
--- a/eg/list.hs
+++ b/eg/list.hs
@@ -56,62 +56,63 @@
 main :: IO ()
 main = do
   conjure "length" length'
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
     ]
 
   conjure "reverse" reverse'
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
     ]
 
   conjure "++" (+++)
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
     ]
 
   conjure "++" (+++)
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "foldr" (foldr :: (Int -> [Int] -> [Int]) -> [Int] -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "foldr" (foldr :: (Int -> [Int] -> [Int]) -> [Int] -> [Int] -> [Int])
     ]
 
   conjure "last" last'
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "null" (null :: [Int] -> Bool)
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "null" (null :: [Int] -> Bool)
     , guard
-    , prim "undefined" (undefined :: Int)
+    , fun "undefined" (undefined :: Int)
     ]
 
-  conjureWith args{maxPatternDepth=2} "last" last'
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "undefined" (undefined :: Int)
+  conjure "last" last'
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "undefined" (undefined :: Int)
+    , maxPatternDepth 2
     ]
 
   conjure "zip" (zip')
-    [ pr ([] :: [(Int,Int)])
-    , prim ":" ((:) :: (Int,Int) -> [(Int,Int)] -> [(Int,Int)])
-    , prim "," ((,) :: Int -> Int -> (Int,Int))
+    [ con ([] :: [(Int,Int)])
+    , fun ":" ((:) :: (Int,Int) -> [(Int,Int)] -> [(Int,Int)])
+    , fun "," ((,) :: Int -> Int -> (Int,Int))
     ]
 
   conjure "\\/" (\/)
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
     ]
 
   conjure "ordered" ordered'
-    [ pr False
-    , pr True
-    , prim "&&" (&&)
-    , prim "||" (||)
-    , prim "<=" ((<=) :: Int -> Int -> Bool)
-    , prim "null" (null :: [Int] -> Bool)
-    , prim "head" (head :: [Int] -> Int)
-    , prim "tail" (tail :: [Int] -> [Int])
+    [ con False
+    , con True
+    , fun "&&" (&&)
+    , fun "||" (||)
+    , fun "<=" ((<=) :: Int -> Int -> Bool)
+    , fun "null" (null :: [Int] -> Bool)
+    , fun "head" (head :: [Int] -> Int)
+    , fun "tail" (tail :: [Int] -> [Int])
     ]
 
   -- for elem, please see eg/setelem.hs
diff --git a/eg/list.txt b/eg/list.txt
--- a/eg/list.txt
+++ b/eg/list.txt
@@ -8,7 +8,7 @@
 -- 2 candidates of size 5
 -- tested 4 candidates
 length []  =  0
-length (x:xs)  =  length xs + 1
+length (x:xs)  =  1 + length xs
 
 reverse :: [Int] -> [Int]
 -- testing 360 combinations of argument values
@@ -123,5 +123,5 @@
 -- 115 candidates of size 11
 -- tested 172 candidates
 ordered []  =  True
-ordered (x:xs)  =  ordered xs && (null xs || x <= head xs)
+ordered (x:xs)  =  (null xs || x <= head xs) && ordered xs
 
diff --git a/eg/maybe.hs b/eg/maybe.hs
--- a/eg/maybe.hs
+++ b/eg/maybe.hs
@@ -48,37 +48,37 @@
 
 main :: IO ()
 main = do
-  conjure "isNothing"     isNothing'   primitives
-  conjure "isJust"        isJust'      primitives
-  conjure "fromMaybe"     fromMaybe'   primitives
-  conjureFromSpec "maybe" maybeSpec    primitives
-  conjure "listToMaybe"   listToMaybe' primitives
-  conjure "maybeToList"   maybeToList' primitives
+  conjure "isNothing"     isNothing'   ingredients
+  conjure "isJust"        isJust'      ingredients
+  conjure "fromMaybe"     fromMaybe'   ingredients
+  conjureFromSpec "maybe" maybeSpec    ingredients
+  conjure "listToMaybe"   listToMaybe' ingredients
+  conjure "maybeToList"   maybeToList' ingredients
 
-  -- only top-level break downs, so would need morePrimitives
-  conjureWith args{maxPatternDepth=2} "catMaybes"     catMaybes'   primitives
-  -- conjure "mapMaybe" mapMaybe' primitives  -- same
+  -- only top-level break downs, so would need moreIngredients
+  conjure "catMaybes"     catMaybes'   (maxPatternDepth 2 : ingredients)
+  -- conjure "mapMaybe" mapMaybe' ingredients  -- same
 
-primitives :: [Prim]
-primitives  =
-  [ pr (Nothing :: Maybe A)
-  , prim "Just" (Just :: A -> Maybe A)
+ingredients :: [Ingredient]
+ingredients  =
+  [ con (Nothing :: Maybe A)
+  , fun "Just" (Just :: A -> Maybe A)
 
-  , pr False
-  , pr True
+  , con False
+  , con True
 
-  , pr ([] :: [A])
-  , prim ":" ((:) :: A -> [A] -> [A])
+  , con ([] :: [A])
+  , fun ":" ((:) :: A -> [A] -> [A])
   ]
 
 {-
-morePrimitives :: [Prim]
-morePrimitives  =  primitives ++
-  [ prim "isNothing" (isNothing :: Maybe A -> Bool)
-  , prim "isJust"    (isJust    :: Maybe A -> Bool)
-  , prim "fromJust"  (fromJust :: Maybe A -> A)
-  , prif (undefined :: A)
-  , prif (undefined :: Maybe A)
-  , prif (undefined :: [A])
+moreIngredients :: [Ingredient]
+moreIngredients  =  ingredients ++
+  [ fun "isNothing" (isNothing :: Maybe A -> Bool)
+  , fun "isJust"    (isJust    :: Maybe A -> Bool)
+  , fun "fromJust"  (fromJust :: Maybe A -> A)
+  , iif (undefined :: A)
+  , iif (undefined :: Maybe A)
+  , iif (undefined :: [A])
   ]
 -}
diff --git a/eg/oddeven.hs b/eg/oddeven.hs
--- a/eg/oddeven.hs
+++ b/eg/oddeven.hs
@@ -1,4 +1,4 @@
--- oddeven.hs: conjuring even and odd from two sets of primitives
+-- oddeven.hs: conjuring even and odd from two sets of ingredients
 --
 -- Copyright (C) 2025 Rudy Matela
 -- Distributed under the 3-Clause BSD licence (see the file LICENSE).
@@ -23,30 +23,30 @@
 
 main :: IO ()
 main = do
-  conjure "odd"  odd  primitives1
-  conjure "even" even primitives1
-  conjure "odd"  odd  primitives2
-  conjure "even" even primitives2
+  conjure "odd"  odd  ingredients1
+  conjure "even" even ingredients1
+  conjure "odd"  odd  ingredients2
+  conjure "even" even ingredients2
 
-primitives1 :: [Prim]
-primitives1 =
-  [ pr (0::Int)
-  , pr (1::Int)
-  , pr (2::Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
+ingredients1 :: [Ingredient]
+ingredients1 =
+  [ con (0::Int)
+  , con (1::Int)
+  , con (2::Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
 
-  , prim "-" ((-) :: Int -> Int -> Int)
-  , pr False
-  , pr True
+  , fun "-" ((-) :: Int -> Int -> Int)
+  , con False
+  , con True
   ]
 
-primitives2 :: [Prim]
-primitives2 =
-  [ pr (0::Int)
-  , pr (1::Int)
-  , pr (2::Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
+ingredients2 :: [Ingredient]
+ingredients2 =
+  [ con (0::Int)
+  , con (1::Int)
+  , con (2::Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
 
-  , prim "`mod`" (mod :: Int -> Int -> Int)
-  , prim "==" ((==) :: Int -> Int -> Bool)
+  , fun "`mod`" (mod :: Int -> Int -> Int)
+  , fun "==" ((==) :: Int -> Int -> Bool)
   ]
diff --git a/eg/peano.hs b/eg/peano.hs
--- a/eg/peano.hs
+++ b/eg/peano.hs
@@ -27,16 +27,16 @@
 main :: IO ()
 main  =  do
   conjure "+" plus
-    [ pr Z
-    , prim "S" S
+    [ con Z
+    , fun "S" S
     ]
 
   -- use + to conjure *
   conjure "*" times
-    [ pr Z
-    , prim "S" S
-    , prim "+" (let p + Z    =  p
-                    p + S q  =  S p + q
+    [ con Z
+    , fun "S" S
+    , fun "+" (let p + Z    =  p
+                   p + S q  =  S p + q
                 in (+))
     ]
 
diff --git a/eg/pow.hs b/eg/pow.hs
--- a/eg/pow.hs
+++ b/eg/pow.hs
@@ -15,22 +15,23 @@
 main  =  do
   -- pow x 0  =  1
   -- pow x y  =  x * pow x (y - 1)
-  conjureWithMaxSize 8 "pow" pow
-    [ pr (0::Int)
-    , pr (1::Int)
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
+  conjure "pow" pow
+    [ con (0::Int)
+    , con (1::Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
     ]
 
   -- pow b 0  =  1
   -- pow b e  =  pow b (halve e) * pow b (halve e) * if odd e then b else 1
   --             2   3  4     5  6 7   8  9    10 11 12 13 14     15     16
   -- out of reach performance wise, OOM at size 9
-  conjureWithMaxSize 6 "pow" pow
-    [ pr (0::Int)
-    , pr (1::Int)
---  , prim "sq" ((\x -> x*x) :: Int -> Int) -- cheat! OOM still
-    , prim "*" ((*) :: Int -> Int -> Int)
-    , prim "halve" ((`div` 2) :: Int -> Int)
-    , prif (undefined :: Int)
+  conjure "pow" pow
+    [ con (0::Int)
+    , con (1::Int)
+--  , fun "sq" ((\x -> x*x) :: Int -> Int) -- cheat! OOM still
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "halve" ((`div` 2) :: Int -> Int)
+    , iif (undefined :: Int)
+    , maxSize 6 -- OOM at size 9
     ]
diff --git a/eg/pow.txt b/eg/pow.txt
--- a/eg/pow.txt
+++ b/eg/pow.txt
@@ -23,5 +23,5 @@
 -- 259 candidates of size 5
 -- 750 candidates of size 6
 -- tested 1169 candidates
-cannot conjure
+pow  =  undefined  -- search exhausted
 
diff --git a/eg/replicate.hs b/eg/replicate.hs
--- a/eg/replicate.hs
+++ b/eg/replicate.hs
@@ -26,33 +26,33 @@
 main :: IO ()
 main = do
   conjure "replicate" replicate'
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
-    , pr ""
-    , prim ":" ((:) :: Char -> String -> String)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
+    , con ""
+    , fun ":" ((:) :: Char -> String -> String)
     ]
 
   -- emulates how MagicHaskeller generates "replicates"
   conjure "replicates" replicates'
-    [ prim "replicate" (replicate :: Int -> String -> [String])
-    , prim "transpose" (transpose :: [[Char]] -> [[Char]])
-    , prim "concat"    (concat :: [String] -> String)
+    [ fun "replicate" (replicate :: Int -> String -> [String])
+    , fun "transpose" (transpose :: [[Char]] -> [[Char]])
+    , fun "concat"    (concat :: [String] -> String)
     ]
 
   -- emulates an alternative generation that works on MagicHaskeller
   conjure "replicates" replicates'
-    [ prim "replicate" (replicate :: Int -> Char -> String)
-    , prim "map"       (map :: (Char -> String) -> String -> [String])
-    , prim "concat"    (concat :: [String] -> String)
+    [ fun "replicate" (replicate :: Int -> Char -> String)
+    , fun "map"       (map :: (Char -> String) -> String -> [String])
+    , fun "concat"    (concat :: [String] -> String)
     ]
 
   -- alternative generation using recursion
   conjure "replicates" replicates'
-    [ pr ""
-    , prim ":" ((:) :: Char -> String -> String)
-    , prim "++" ((++) :: String -> String -> String)
-    , prim "replicate" (replicate :: Int -> Char -> String)
+    [ con ""
+    , fun ":" ((:) :: Char -> String -> String)
+    , fun "++" ((++) :: String -> String -> String)
+    , fun "replicate" (replicate :: Int -> Char -> String)
     ]
 
 replicates n []  =  []
diff --git a/eg/setelem.hs b/eg/setelem.hs
--- a/eg/setelem.hs
+++ b/eg/setelem.hs
@@ -18,23 +18,23 @@
 main :: IO ()
 main = do
   conjure "elem" (elem')
-    [ pr ([] :: [Int])
-    , pr True
-    , pr False
-    , prim "||" (||)
-    , prim "&&" (&&)
-    , prim "not" not
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "==" ((==) :: Int -> Int -> Bool)
+    [ con ([] :: [Int])
+    , con True
+    , con False
+    , fun "||" (||)
+    , fun "&&" (&&)
+    , fun "not" not
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "==" ((==) :: Int -> Int -> Bool)
     ]
 
   conjure "set" (set')
-    [ pr ([] :: [Int])
-    , pr True
-    , pr False
-    , prim "&&" (&&)
-    , prim "||" (||)
-    , prim "not" not
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "elem" (elem :: Int -> [Int] -> Bool)
+    [ con ([] :: [Int])
+    , con True
+    , con False
+    , fun "&&" (&&)
+    , fun "||" (||)
+    , fun "not" not
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "elem" (elem :: Int -> [Int] -> Bool)
     ]
diff --git a/eg/setelem.txt b/eg/setelem.txt
--- a/eg/setelem.txt
+++ b/eg/setelem.txt
@@ -11,7 +11,7 @@
 -- 16 candidates of size 8
 -- tested 19 candidates
 elem x []  =  False
-elem x (y:xs)  =  elem x xs || x == y
+elem x (y:xs)  =  x == y || elem x xs
 
 set :: [Int] -> Bool
 -- testing 360 combinations of argument values
@@ -26,5 +26,5 @@
 -- 4 candidates of size 8
 -- tested 6 candidates
 set []  =  True
-set (x:xs)  =  set xs && not (elem x xs)
+set (x:xs)  =  not (elem x xs) && set xs
 
diff --git a/eg/sort.hs b/eg/sort.hs
--- a/eg/sort.hs
+++ b/eg/sort.hs
@@ -47,27 +47,28 @@
   -- sort []  =  []
   -- sort (x:xs)  =  insert x (sort xs)
   conjure "sort" sort'
-    [ pr ([] :: [Int])
-    , prim "insert" (insert :: Int -> [Int] -> [Int])
-    , prim "head" (head :: [Int] -> Int)
-    , prim "tail" (tail :: [Int] -> [Int])
-    , prim "null" (null :: [Int] -> Bool)
+    [ con ([] :: [Int])
+    , fun "insert" (insert :: Int -> [Int] -> [Int])
+    , fun "head" (head :: [Int] -> Int)
+    , fun "tail" (tail :: [Int] -> [Int])
+    , fun "null" (null :: [Int] -> Bool)
     ]
 
   -- now through fold
   -- sort xs  =  foldr insert [] xs
   conjure "sort" sort'
-    [ pr ([] :: [Int])
-    , prim "insert" (insert :: Int -> [Int] -> [Int])
-    , prim "foldr" (foldr :: (Int -> [Int] -> [Int]) -> [Int] -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun "insert" (insert :: Int -> [Int] -> [Int])
+    , fun "foldr" (foldr :: (Int -> [Int] -> [Int]) -> [Int] -> [Int] -> [Int])
     ]
 
   -- an insert function
-  conjureWith args{target=50400} "insert" insert'
-    [ prim "[]" ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "<=" ((<=) :: Int -> Int -> Bool)
+  conjure "insert" insert'
+    [ fun "[]" ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "<=" ((<=) :: Int -> Int -> Bool)
     , guard
+    , target 50400
     ]
 
   -- qsort []  =  []                           -- 1
@@ -77,23 +78,24 @@
   -- but is not generated because of the deconstruction restriction.
   -- The following does generate a correct but inneficient version of qsort.
   conjure "qsort" sort'
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
-    , prim "<=" ((<=) :: Int -> Int -> Bool)
-    , prim ">"  ((>)  :: Int -> Int -> Bool)
-    , prim "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
+    , fun "<=" ((<=) :: Int -> Int -> Bool)
+    , fun ">"  ((>)  :: Int -> Int -> Bool)
+    , fun "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])
     ]
 
   -- if we disable the descent requirement, we get the efficient qsort
   -- though with a larger search space
-  conjureWith args{requireDescent=False} "qsort" sort'
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
-    , prim "<=" ((<=) :: Int -> Int -> Bool)
-    , prim ">"  ((>)  :: Int -> Int -> Bool)
-    , prim "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])
+  conjure "qsort" sort'
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
+    , fun "<=" ((<=) :: Int -> Int -> Bool)
+    , fun ">"  ((>)  :: Int -> Int -> Bool)
+    , fun "filter" (filter :: (Int -> Bool) -> [Int] -> [Int])
+    , dontRequireDescent
     ]
 
   -- found!  candidate #1703311 @ size 22
@@ -103,16 +105,19 @@
   --   | x <= y  =  x:merge xs (y:ys)
   --   | otherwise  =  merge (y:x:xs) ys
   -- set target to 2 000 000 to reach it
-  conjureWith args{target=10080, maxTests=1080} "merge" merge'
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "<=" ((<=) :: Int -> Int -> Bool)
+  conjure "merge" merge'
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "<=" ((<=) :: Int -> Int -> Bool)
     , guard
+    , maxTests 1080
+    , target 10080 -- set to 2 000 000 to reach solution
     ]
 
   -- unreachable: needs about 26, but can only reach 16
-  conjureWith args{target=1080} "merge" merge'
-    [ prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "compare" (compare :: Int -> Int -> Ordering)
-    , primOrdCaseFor (undefined :: [Int])
+  conjure "merge" merge'
+    [ fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "compare" (compare :: Int -> Int -> Ordering)
+    , ordcase (undefined :: [Int])
+    , target 1080
     ]
diff --git a/eg/sort.txt b/eg/sort.txt
--- a/eg/sort.txt
+++ b/eg/sort.txt
@@ -107,7 +107,7 @@
 -- 4204 candidates of size 14
 -- 5426 candidates of size 15
 -- tested 12326 candidates
-cannot conjure
+merge  =  undefined  -- search exhausted
 
 merge :: [Int] -> [Int] -> [Int]
 -- testing 360 combinations of argument values
@@ -126,5 +126,5 @@
 -- 588 candidates of size 12
 -- 958 candidates of size 13
 -- tested 1876 candidates
-cannot conjure
+merge  =  undefined  -- search exhausted
 
diff --git a/eg/spec.hs b/eg/spec.hs
--- a/eg/spec.hs
+++ b/eg/spec.hs
@@ -11,12 +11,12 @@
                    && square 1 == 1
                    && square 2 == 4
 
-squarePrimitives :: [Prim]
-squarePrimitives  =
-  [ pr (0::Int)
-  , pr (1::Int)
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "*" ((*) :: Int -> Int -> Int)
+squareIngredients :: [Ingredient]
+squareIngredients  =
+  [ con (0::Int)
+  , con (1::Int)
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "*" ((*) :: Int -> Int -> Int)
   ]
 
 squarePropertySpec :: (Int -> Int) -> Bool
@@ -32,13 +32,13 @@
              && sum [1,2]   == 3
              && sum [3,4,5] == 12
 
-sumPrimitives :: [Prim]
-sumPrimitives  =
-  [ prim "null" (null :: [Int] -> Bool)
-  , pr (0::Int)
-  , prim "+"    ((+) :: Int -> Int -> Int)
-  , prim "head" (head :: [Int] -> Int)
-  , prim "tail" (tail :: [Int] -> [Int])
+sumIngredients :: [Ingredient]
+sumIngredients  =
+  [ fun "null" (null :: [Int] -> Bool)
+  , con (0::Int)
+  , fun "+"    ((+) :: Int -> Int -> Int)
+  , fun "head" (head :: [Int] -> Int)
+  , fun "tail" (tail :: [Int] -> [Int])
   ]
 
 
@@ -47,18 +47,18 @@
               && [2,3]   ++ []      == [2,3]
               && [4,5,6] ++ [7,8,9] == [4,5,6,7,8,9]
 
-appPrimitives :: [Prim]
-appPrimitives =
-  [ prim "null" (null :: [Int] -> Bool)
-  , prim ":"    ((:) :: Int -> [Int] -> [Int])
-  , prim "head" (head :: [Int] -> Int)
-  , prim "tail" (tail :: [Int] -> [Int])
+appIngredients :: [Ingredient]
+appIngredients =
+  [ fun "null" (null :: [Int] -> Bool)
+  , fun ":"    ((:) :: Int -> [Int] -> [Int])
+  , fun "head" (head :: [Int] -> Int)
+  , fun "tail" (tail :: [Int] -> [Int])
   ]
 
 
 main :: IO ()
 main = do
-  conjureFromSpec "square" squareSpec squarePrimitives
-  conjureFromSpec "square" squarePropertySpec squarePrimitives
-  conjureFromSpec "sum" sumSpec sumPrimitives
-  conjureFromSpec "++"  appSpec appPrimitives
+  conjureFromSpec "square" squareSpec squareIngredients
+  conjureFromSpec "square" squarePropertySpec squareIngredients
+  conjureFromSpec "sum" sumSpec sumIngredients
+  conjureFromSpec "++"  appSpec appIngredients
diff --git a/eg/subset.hs b/eg/subset.hs
--- a/eg/subset.hs
+++ b/eg/subset.hs
@@ -44,16 +44,16 @@
   -- subset [] ys  =  True
   -- subset (x:xs) ys  =  elem x ys && subset xs ys
   conjure "subset" (subset')
-    [ pr ([] :: [Int])
-    , pr True
-    , pr False
-    , prim "&&" (&&)
-    , prim "||" (||)
-    , prim "elem" (elem :: Int -> [Int] -> Bool)
+    [ con ([] :: [Int])
+    , con True
+    , con False
+    , fun "&&" (&&)
+    , fun "||" (||)
+    , fun "elem" (elem :: Int -> [Int] -> Bool)
     ]
 
   -- subset xs ys  =  sort xs `isSubsequenceOf` sort ys
   conjure "subset" (subset')
-    [ prim "sort" (sort :: [Int] -> [Int])
-    , prim "`isSubsequenceOf`" (isSubsequenceOf :: [Int] -> [Int] -> Bool)
+    [ fun "sort" (sort :: [Int] -> [Int])
+    , fun "`isSubsequenceOf`" (isSubsequenceOf :: [Int] -> [Int] -> Bool)
     ]
diff --git a/eg/subset.txt b/eg/subset.txt
--- a/eg/subset.txt
+++ b/eg/subset.txt
@@ -11,7 +11,7 @@
 -- 176 candidates of size 8
 -- tested 176 candidates
 subset [] xs  =  True
-subset (x:xs) ys  =  subset xs ys && elem x ys
+subset (x:xs) ys  =  elem x ys && subset xs ys
 
 subset :: [Int] -> [Int] -> Bool
 -- testing 44 combinations of argument values
diff --git a/eg/take-drop.hs b/eg/take-drop.hs
--- a/eg/take-drop.hs
+++ b/eg/take-drop.hs
@@ -27,20 +27,20 @@
   -- drop x []  =  []                   -- 2
   -- drop x (y:xs)  =  drop (x - 1) xs  -- 7
   conjure "drop" (drop' :: Int -> [A] -> [A])
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , pr ([] :: [A])
-    , prim ":" ((:) :: A -> [A] -> [A])
-    , prim "-" ((-) :: Int -> Int -> Int)
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , con ([] :: [A])
+    , fun ":" ((:) :: A -> [A] -> [A])
+    , fun "-" ((-) :: Int -> Int -> Int)
     ]
 
   -- take 0 xs  =  []                     -- 1
   -- take x []  =  []                     -- 2
   -- take x (y:xs)  =  y:take (x - 1) xs  -- 9
   conjure "take" (take' :: Int -> [A] -> [A])
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , pr ([] :: [A])
-    , prim "-" ((-) :: Int -> Int -> Int)
-    , prim ":" ((:) :: A -> [A] -> [A])
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , con ([] :: [A])
+    , fun "-" ((-) :: Int -> Int -> Int)
+    , fun ":" ((:) :: A -> [A] -> [A])
     ]
diff --git a/eg/tapps.hs b/eg/tapps.hs
--- a/eg/tapps.hs
+++ b/eg/tapps.hs
@@ -21,45 +21,45 @@
 
 main :: IO ()
 main = do
-  conjure "third"   third    primitives
-  conjure "product" product' primitives
-  conjure "product" product' primitivesWithFold
+  conjure "third"   third    ingredients
+  conjure "product" product' ingredients
+  conjure "product" product' ingredientsWithFold
 
-primitives :: [Prim]
-primitives =
-  [ pr (0 :: Int)
-  , pr (1 :: Int)
+ingredients :: [Ingredient]
+ingredients =
+  [ con (0 :: Int)
+  , con (1 :: Int)
 #if __GLASGOW_HASKELL__ < 800
-  , prim "+" ((+) :: Int -> Int -> Int)
-  , prim "*" ((*) :: Int -> Int -> Int)
-  , prim "null" (null :: [Int] -> Bool)
-  , prim "head" (head :: [Int] -> Int)
-  , prim "tail" (tail :: [Int] -> [Int])
+  , fun "+" ((+) :: Int -> Int -> Int)
+  , fun "*" ((*) :: Int -> Int -> Int)
+  , fun "null" (null :: [Int] -> Bool)
+  , fun "head" (head :: [Int] -> Int)
+  , fun "tail" (tail :: [Int] -> [Int])
 #else
-  , prim "+" ((+) @Int)
-  , prim "*" ((*) @Int)
+  , fun "+" ((+) @Int)
+  , fun "*" ((*) @Int)
 -- the following #if was added just for dramatic effect (see notes below)
 #if __GLASGOW_HASKELL__ < 710
-  , prim "null" (null @Int)
+  , fun "null" (null @Int)
 #else
-  , prim "null" (null @[] @Int)
+  , fun "null" (null @[] @Int)
 #endif
-  , prim "head" (head @Int)
-  , prim "tail" (tail @Int)
+  , fun "head" (head @Int)
+  , fun "tail" (tail @Int)
 #endif
   ]
 
-primitivesWithFold :: [Prim]
+ingredientsWithFold :: [Ingredient]
 #if __GLASGOW_HASKELL__ < 800
-primitivesWithFold  =
-    prim "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
-  : primitives
+ingredientsWithFold  =
+    fun "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int)
+  : ingredients
 #else
 -- the following #if was added just for dramatic effect (see notes below)
 #if __GLASGOW_HASKELL__ < 710
-primitivesWithFold  =  prim "foldr" (foldr @Int @Int) : primitives
+ingredientsWithFold  =  fun "foldr" (foldr @Int @Int) : ingredients
 #else
-primitivesWithFold  =  prim "foldr" (foldr @[] @Int @Int) : primitives
+ingredientsWithFold  =  fun "foldr" (foldr @[] @Int @Int) : ingredients
 #endif
 #endif
 
diff --git a/eg/these.hs b/eg/these.hs
--- a/eg/these.hs
+++ b/eg/these.hs
@@ -74,43 +74,46 @@
 main :: IO ()
 main  =  do
   conjure "fromThese" fromThese'
-    [ prim "," ((,) :: A -> B -> (A,B))
+    [ fun "," ((,) :: A -> B -> (A,B))
     ]
 
   conjure "listhese" listhese'
-    [ pr ([] :: [A])
-    , prim ":" ((:) :: A -> [A] -> [A])
+    [ con ([] :: [A])
+    , fun ":" ((:) :: A -> [A] -> [A])
     ]
 
   conjure "cathis" cathis'
-    [ pr ([] :: [A])
-    , prim ":" ((:) :: A -> [A] -> [A])
-    , prim "isThis" (isThis :: These A B -> Bool)
-    , prim "fromThis" (fromThis :: These A B -> A)
+    [ con ([] :: [A])
+    , fun ":" ((:) :: A -> [A] -> [A])
+    , fun "isThis" (isThis :: These A B -> Bool)
+    , fun "fromThis" (fromThis :: These A B -> A)
     , guard
     ]
 
   conjure "cathat" cathat'
-    [ pr ([] :: [B])
-    , prim ":" ((:) :: B -> [B] -> [B])
-    , prim "isThat" (isThat :: These A B -> Bool)
-    , prim "fromThat" (fromThat :: These A B -> B)
+    [ con ([] :: [B])
+    , fun ":" ((:) :: B -> [B] -> [B])
+    , fun "isThat" (isThat :: These A B -> Bool)
+    , fun "fromThat" (fromThat :: These A B -> B)
     , guard
     ]
 
-  conjureWith args{maxPatternDepth = 2} "cathis" cathis'
-    [ pr ([] :: [A])
-    , prim ":" ((:) :: A -> [A] -> [A])
+  conjure "cathis" cathis'
+    [ con ([] :: [A])
+    , fun ":" ((:) :: A -> [A] -> [A])
+    , maxPatternDepth 2
     ]
 
-  conjureWith args{maxPatternDepth = 2} "cathat" cathat'
-    [ pr ([] :: [B])
-    , prim ":" ((:) :: B -> [B] -> [B])
+  conjure "cathat" cathat'
+    [ con ([] :: [B])
+    , fun ":" ((:) :: B -> [B] -> [B])
+    , maxPatternDepth 2
     ]
 
-  conjureWith args{maxPatternDepth = 2} "cathese" cathese'
-    [ pr ([] :: [A])
-    , prim ":" ((:) :: A -> [A] -> [A])
+  conjure "cathese" cathese'
+    [ con ([] :: [A])
+    , fun ":" ((:) :: A -> [A] -> [A])
+    , maxPatternDepth 2
     ]
   -- cathese []  =  []
   -- cathese (Neither : ts)  =  cathese ts
diff --git a/eg/tree.hs b/eg/tree.hs
--- a/eg/tree.hs
+++ b/eg/tree.hs
@@ -97,72 +97,73 @@
 main :: IO ()
 main = do
   conjure "leftmost" leftmost
-    [ prim "undefined" (undefined :: Int)
-    , prif (undefined :: Int)
-    , prim "nil" nil
+    [ fun "undefined" (undefined :: Int)
+    , iif (undefined :: Int)
+    , fun "nil" nil
     ]
 
   conjure "rightmost" rightmost
-    [ prim "undefined" (undefined :: Int)
-    , prif (undefined :: Int)
-    , prim "nil" nil
+    [ fun "undefined" (undefined :: Int)
+    , iif (undefined :: Int)
+    , fun "nil" nil
     ]
 
   conjure "size" size
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "nil" nil
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "nil" nil
     ]
 
   conjure "height" height
-    [ pr (0 :: Int)
-    , pr (1 :: Int)
-    , pr (-1 :: Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "max" (max :: Int -> Int -> Int)
-    , prim "nil" nil
+    [ con (0 :: Int)
+    , con (1 :: Int)
+    , con (-1 :: Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "max" (max :: Int -> Int -> Int)
+    , fun "nil" nil
     ]
 
   conjure "mem" mem
-    [ pr False
-    , prim "||" (||)
-    , prim "==" ((==) :: Int -> Int -> Bool)
+    [ con False
+    , fun "||" (||)
+    , fun "==" ((==) :: Int -> Int -> Bool)
     ]
 
   -- unreachable: needs size 22 but OOMs at 19/20 (v0.5.16)
-  conjureWithMaxSize 12 "ordered" ordered
-    [ pr True
-    , pr False
-    , prim "&&" (&&)
-    , prim "||" (||)
-    , prim "<" ((<) :: Int -> Int -> Bool)
-    , prim "rightmost" rightmost
-    , prim "leftmost" leftmost
-    , prim "nil" nil
+  conjure "ordered" ordered
+    [ con True
+    , con False
+    , fun "&&" (&&)
+    , fun "||" (||)
+    , fun "<" ((<) :: Int -> Int -> Bool)
+    , fun "rightmost" rightmost
+    , fun "leftmost" leftmost
+    , fun "nil" nil
+    , maxSize 12
     ]
 
   conjure "ordered" ordered
-    [ prim "strictlyOrdered" (strictlyOrdered :: [Int] -> Bool)
-    , prim "inorder" inorder
+    [ fun "strictlyOrdered" (strictlyOrdered :: [Int] -> Bool)
+    , fun "inorder" inorder
     ]
 
-  conjureWithMaxSize 12 "preorder" preorder
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
+  conjure "preorder" preorder
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
     ]
 
-  conjureWithMaxSize 12 "inorder" inorder
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
+  conjure "inorder" inorder
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
     ]
 
-  conjureWithMaxSize 12 "posorder" posorder
-    [ pr ([] :: [Int])
-    , prim ":" ((:) :: Int -> [Int] -> [Int])
-    , prim "++" ((++) :: [Int] -> [Int] -> [Int])
+  conjure "posorder" posorder
+    [ con ([] :: [Int])
+    , fun ":" ((:) :: Int -> [Int] -> [Int])
+    , fun "++" ((++) :: [Int] -> [Int] -> [Int])
     ]
 
 
diff --git a/eg/tree.txt b/eg/tree.txt
--- a/eg/tree.txt
+++ b/eg/tree.txt
@@ -43,7 +43,7 @@
 -- 16 candidates of size 8
 -- tested 32 candidates
 size Leaf  =  0
-size (Node t1 x t2)  =  size t1 + (size t2 + 1)
+size (Node t1 x t2)  =  size t1 + (1 + size t2)
 
 height :: Tree -> Int
 -- testing 360 combinations of argument values
@@ -77,7 +77,7 @@
 -- 36 candidates of size 12
 -- tested 42 candidates
 mem x Leaf  =  False
-mem x (Node t1 y t2)  =  mem x t1 || (mem x t2 || x == y)
+mem x (Node t1 y t2)  =  mem x t1 || (x == y || mem x t2)
 
 ordered :: Tree -> Bool
 -- testing 360 combinations of argument values
@@ -95,7 +95,7 @@
 -- 418 candidates of size 11
 -- 1064 candidates of size 12
 -- tested 1639 candidates
-cannot conjure
+ordered  =  undefined  -- search exhausted
 
 ordered :: Tree -> Bool
 -- testing 360 combinations of argument values
diff --git a/eg/tri.hs b/eg/tri.hs
--- a/eg/tri.hs
+++ b/eg/tri.hs
@@ -12,7 +12,7 @@
 main :: IO ()
 main  =  do
   conjure "tri" tri
-    [ pr (1::Int)
-    , prim "+" ((+) :: Int -> Int -> Int)
-    , prim "-" ((-) :: Int -> Int -> Int)
+    [ con (1::Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
     ]
diff --git a/eg/tuple.hs b/eg/tuple.hs
--- a/eg/tuple.hs
+++ b/eg/tuple.hs
@@ -9,7 +9,7 @@
 -- First, all functions from Data.Tuple
 -- Though their types have been simplified to (A, A),
 -- they might as well have had (A, B), (B, A), etc in types.
--- This makes it to use a single background primitives list for everything.
+-- This makes it to easier to use a list of ingredients for everything.
 
 fst' :: (A,A) -> A
 fst' (0,1)  =  0
@@ -54,15 +54,13 @@
 -- now two functions that are a bit more interesting:
 
 pairwise :: [A] -> [(A,A)]
-pairwise []  =  []
--- pairwise [x]  =  []
-pairwise [x,y]  =  [(x,y)]
--- pairwise [x,y,z]  =  [] -- TODO: why this does not work
-pairwise [x,y,z,w]  =  [(x,y), (z,w)]
--- pairwise [0,1,2,3]  =  [(0,1), (2,3)]
--- pairwise [0,1,0,1]  =  [(0,1), (0,1)]
--- pairwise [0,0,0,0,0]  =  [(0,0), (0,0)]
--- pairwise [0,0,0,0,0,0]  =  [(0,0), (0,0), (0,0)]
+pairwise [0,1,2,3]  =  [(0,1), (2,3)]
+pairwise [0,1,0,1]  =  [(0,1), (0,1)]
+pairwise [0,0,0,0,0,0]  =  [(0,0), (0,0), (0,0)]
+-- alt:
+-- pairwise [x,y]  =  [(x,y)]
+-- pairwise [x,y,z,w]  =  [(x,y), (z,w)]
+-- notice above even lists are required for the shallow-pattern solution
 
 catpairs :: [(A,A)] -> [A]
 catpairs [(x,y)]  =  [x,y]
@@ -73,35 +71,35 @@
   -- the following 5 are pretty easy to Conjure:
   conjure "fst"  fst'   []
   conjure "snd"  snd'   []
-  conjure "swap" swap'  primitives
-  conjureFromSpec "curry"     currySpec primitives
-  conjureFromSpec "uncurry" uncurrySpec primitives
+  conjure "swap" swap'  ingredients
+  conjureFromSpec "curry"     currySpec ingredients
+  conjureFromSpec "uncurry" uncurrySpec ingredients
 
   -- these are more interesting:
-  conjure "pairwise" pairwise primitives
-  conjure "catpairs" catpairs primitives
+  conjure "pairwise" pairwise ingredients
+  conjure "catpairs" catpairs ingredients
 
   -- by increasing the pattern depth, we find shorter versions:
-  conjureWith args{maxPatternDepth=2} "pairwise" pairwise primitives
-  conjureWith args{maxPatternDepth=2} "catpairs" catpairs primitives
+  conjure "pairwise" pairwise (maxPatternDepth 2:ingredients)
+  conjure "catpairs" catpairs (maxPatternDepth 2:ingredients)
 
-primitives :: [Prim]
-primitives  =
+ingredients :: [Ingredient]
+ingredients  =
   -- pairs
-  [ prim "," ((,) :: A -> A -> (A,A))
-  , prim "fst" (fst :: (A,A) -> A)
-  , prim "snd" (snd :: (A,A) -> A)
+  [ fun "," ((,) :: A -> A -> (A,A))
+  , fun "fst" (fst :: (A,A) -> A)
+  , fun "snd" (snd :: (A,A) -> A)
 
   -- lists
-  , prim "[]" ([] :: [A])
-  , prim ":" ((:) :: A -> [A] -> [A])
-  , prim "null" (null :: [A] -> Bool)
-  , prim "head" (head :: [A] -> A)
-  , prim "tail" (tail :: [A] -> [A])
+  , fun "[]" ([] :: [A])
+  , fun ":" ((:) :: A -> [A] -> [A])
+  , fun "null" (null :: [A] -> Bool)
+  , fun "head" (head :: [A] -> A)
+  , fun "tail" (tail :: [A] -> [A])
 
   -- lists of pairs
-  , prim "[]" ([] :: [(A,A)])
-  , prim ":" ((:) :: (A,A) -> [(A,A)] -> [(A,A)])
+  , fun "[]" ([] :: [(A,A)])
+  , fun ":" ((:) :: (A,A) -> [(A,A)] -> [(A,A)])
 
   -- allow guards
   , guard
diff --git a/eg/tuple.txt b/eg/tuple.txt
--- a/eg/tuple.txt
+++ b/eg/tuple.txt
@@ -43,7 +43,7 @@
 uncurry f (x,y)  =  f x y
 
 pairwise :: [A] -> [(A,A)]
--- testing 360 combinations of argument values
+-- testing 3 combinations of argument values
 -- pruning with 10/10 rules
 -- 1 candidates of size 1
 -- 0 candidates of size 2
@@ -75,7 +75,7 @@
 catpairs (xy:xys)  =  fst xy:snd xy:catpairs xys
 
 pairwise :: [A] -> [(A,A)]
--- testing 360 combinations of argument values
+-- testing 3 combinations of argument values
 -- pruning with 10/10 rules
 -- 1 candidates of size 1
 -- 0 candidates of size 2
diff --git a/mk/depend.mk b/mk/depend.mk
--- a/mk/depend.mk
+++ b/mk/depend.mk
@@ -8,10 +8,11 @@
   mk/toplibs
 bench/candidates.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -25,10 +26,11 @@
   mk/toplibs
 bench/carry-on.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -42,10 +44,11 @@
   mk/toplibs
 bench/erroneous.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -59,10 +62,11 @@
   mk/toplibs
 bench/gps2.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -76,10 +80,11 @@
   mk/toplibs
 bench/gps.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -93,10 +98,11 @@
   mk/toplibs
 bench/ill-hit.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -110,10 +116,11 @@
   mk/toplibs
 bench/longshot.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -127,10 +134,11 @@
   mk/toplibs
 bench/lowtests.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -144,10 +152,11 @@
   mk/toplibs
 bench/p12.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -161,10 +170,11 @@
   mk/toplibs
 bench/p30.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -178,10 +188,11 @@
   mk/toplibs
 bench/redundants.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -195,10 +206,11 @@
   mk/toplibs
 bench/self.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -212,10 +224,11 @@
   mk/toplibs
 bench/strategies.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -229,10 +242,11 @@
   mk/toplibs
 bench/terpret.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -246,10 +260,11 @@
   mk/toplibs
 bench/unique.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -263,10 +278,11 @@
   mk/toplibs
 bench/weird.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -280,10 +296,11 @@
   mk/toplibs
 eg/arith.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -297,10 +314,11 @@
   mk/toplibs
 eg/bits.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -314,10 +332,11 @@
   mk/toplibs
 eg/bools.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -331,10 +350,11 @@
   mk/toplibs
 eg/bst.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -348,10 +368,11 @@
   mk/toplibs
 eg/colin/IntFuns.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -365,10 +386,11 @@
   mk/toplibs
 eg/colin/ListFuns.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -382,10 +404,11 @@
   mk/toplibs
 eg/count.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -399,10 +422,11 @@
   mk/toplibs
 eg/dupos.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -416,10 +440,11 @@
   mk/toplibs
 eg/either.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -433,10 +458,11 @@
   mk/toplibs
 eg/factorial.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -450,10 +476,11 @@
   mk/toplibs
 eg/fib01.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -467,10 +494,11 @@
   mk/toplibs
 eg/fibonacci.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -484,10 +512,11 @@
   mk/toplibs
 eg/gcd.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -501,10 +530,11 @@
   mk/toplibs
 eg/higher.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -518,10 +548,11 @@
   mk/toplibs
 eg/id.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -535,10 +566,11 @@
   mk/toplibs
 eg/ints.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -552,10 +584,11 @@
   mk/toplibs
 eg/list.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -569,10 +602,11 @@
   mk/toplibs
 eg/maybe.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -586,10 +620,11 @@
   mk/toplibs
 eg/oddeven.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -603,10 +638,11 @@
   mk/toplibs
 eg/peano.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -620,10 +656,11 @@
   mk/toplibs
 eg/pow.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -637,10 +674,11 @@
   mk/toplibs
 eg/replicate.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -654,10 +692,11 @@
   mk/toplibs
 eg/setelem.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -671,10 +710,11 @@
   mk/toplibs
 eg/sort.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -688,10 +728,11 @@
   mk/toplibs
 eg/spec.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -705,10 +746,11 @@
   mk/toplibs
 eg/subset.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -722,10 +764,11 @@
   mk/toplibs
 eg/take-drop.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -739,10 +782,11 @@
   mk/toplibs
 eg/tapps.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -756,10 +800,11 @@
   mk/toplibs
 eg/these.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -773,10 +818,11 @@
   mk/toplibs
 eg/tree.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -790,10 +836,11 @@
   mk/toplibs
 eg/tri.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -807,10 +854,11 @@
   mk/toplibs
 eg/tuple.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -821,10 +869,11 @@
   eg/tuple.hs
 mk/All.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -837,10 +886,11 @@
   test/Test.hs \
   test/Test/ListableExpr.hs \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -884,9 +934,10 @@
   mk/toplibs
 src/Conjure/Engine.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -896,12 +947,19 @@
 src/Conjure/Expr.o: \
   src/Conjure/Utils.hs \
   src/Conjure/Expr.hs
+src/Conjure/Ingredient.o: \
+  src/Conjure/Utils.hs \
+  src/Conjure/Ingredient.hs \
+  src/Conjure/Expr.hs \
+  src/Conjure/Defn.hs \
+  src/Conjure/Conjurable.hs
 src/Conjure.o: \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -909,12 +967,6 @@
   src/Conjure/Defn.hs \
   src/Conjure/Conjurable.hs \
   src/Conjure/Conjurable/Derive.hs
-src/Conjure/Prim.o: \
-  src/Conjure/Utils.hs \
-  src/Conjure/Prim.hs \
-  src/Conjure/Expr.hs \
-  src/Conjure/Defn.hs \
-  src/Conjure/Conjurable.hs
 src/Conjure/Reason.o: \
   src/Conjure/Utils.hs \
   src/Conjure/Reason.hs \
@@ -925,6 +977,8 @@
   src/Conjure/Expr.hs \
   src/Conjure/Defn.hs \
   src/Conjure/Conjurable.hs
+src/Conjure/Settings.o: \
+  src/Conjure/Settings.hs
 src/Conjure/Utils.o: \
   src/Conjure/Utils.hs
 test/conjurable.o: \
@@ -932,10 +986,11 @@
   test/Test/ListableExpr.hs \
   test/conjurable.hs \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -953,10 +1008,11 @@
   test/Test/ListableExpr.hs \
   test/defn.hs \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -974,10 +1030,11 @@
   test/Test/ListableExpr.hs \
   test/derive.hs \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -995,10 +1052,11 @@
   test/Test/ListableExpr.hs \
   test/expr.hs \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -1011,15 +1069,34 @@
   test/Test/ListableExpr.hs \
   test/expr.hs \
   mk/toplibs
+test/factorial.o: \
+  test/factorial.hs \
+  src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
+  src/Conjure/Red.hs \
+  src/Conjure/Reason.hs \
+  src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
+  src/Conjure/Expr.hs \
+  src/Conjure/Engine.hs \
+  src/Conjure/Defn/Test.hs \
+  src/Conjure/Defn/Redundancy.hs \
+  src/Conjure/Defn.hs \
+  src/Conjure/Conjurable.hs \
+  src/Conjure/Conjurable/Derive.hs
+test/factorial: \
+  test/factorial.hs \
+  mk/toplibs
 test/red.o: \
   test/Test.hs \
   test/Test/ListableExpr.hs \
   test/red.hs \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -1038,10 +1115,11 @@
   test/Test.hs \
   test/Test/ListableExpr.hs \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
@@ -1058,10 +1136,11 @@
   test/Test.hs \
   test/Test/ListableExpr.hs \
   src/Conjure/Utils.hs \
+  src/Conjure/Settings.hs \
   src/Conjure/Red.hs \
   src/Conjure/Reason.hs \
-  src/Conjure/Prim.hs \
   src/Conjure.hs \
+  src/Conjure/Ingredient.hs \
   src/Conjure/Expr.hs \
   src/Conjure/Engine.hs \
   src/Conjure/Defn/Test.hs \
diff --git a/mk/haddock-i b/mk/haddock-i
--- a/mk/haddock-i
+++ b/mk/haddock-i
@@ -2,35 +2,46 @@
 #
 # haddock-i: list haddock's -i parameters.
 #
-# Copyright (c) 2015-2024 Rudy Matela.
+# Copyright (c) 2015-2025 Rudy Matela.
 # Distributed under the 3-Clause BSD licence.
 #
-# $ haddock-i <package1> <package2> ... <packageN>
+# $ haddock-i
 #
 # will print -i parameters necessary for haddock to link to Haddock
 # documentation installed on your system, so you can:
 #
-# $ haddock-i base template-haskell | xargs haddock <files>
-err() {
-	echo "$@" > /dev/stderr
-}
+# $ haddock-i | xargs haddock <files>
 
-errxit() {
-	err "$@"
-	exit 1
+# This is a grep/sed/bash hack.
+# It works for all my packages,
+# but it isn't foolproof,
+# use with care.
+list-deps() {
+	cat *.cabal |
+	sed -e 's/  */\n/g' |
+	grep -A 999 build-depends: |
+	tail -n +2 |
+	grep -v '^$' |
+	while read tok
+	do
+		echo $tok | grep -q :$ && break
+		# TODO: make this slightly more efficient
+		echo $tok | grep -q '^[a-zA-Z-]*$' || continue
+		[ "$tok" == "if" ] && continue
+		echo "$tok"
+	done
 }
 
-iface-for() {
-	ghc-pkg field $1 haddock-interfaces | sort -rV | head -1 | sed "s/.*: //"
+find-find-args() {
+	echo '-name this-should-not-match-anything.haddock'
+	list-deps |
+	sed -e 's/^/-o -name /;s/$/.haddock/'
 }
 
-html-for() {
-	ghc-pkg field $1 haddock-html       | sort -rV | head -1 | sed "s/.*: //"
-}
+realghc=$(basename $(readlink -f /usr/bin/ghc))
 
-for pkg in "$@"
-do
-	iface=$(iface-for $pkg)
-	html=$(html-for $pkg)
-	[ -d "$html" -a -f "$iface" ] && echo "-i$html,$iface" || err "haddock-i: warning: could not find interface file for $pkg"
-done
+find \
+	/usr/share/doc/ghc/html/libraries \
+	~/.cabal/store/$realghc \
+	$(find-find-args) |
+sed -e 's/^/-i /'
diff --git a/mk/haskell.mk b/mk/haskell.mk
--- a/mk/haskell.mk
+++ b/mk/haskell.mk
@@ -117,7 +117,7 @@
 	@echo "(on Arch Linux, use: cabal haddock --for-hackage --haddock-options=--optghc=-dynamic)"
 
 doc/index.html: $(LIB_HSS)
-	./mk/haddock-i $(LIB_DEPS) | xargs \
+	./mk/haddock-i | xargs \
 	$(HADDOCK) --html -odoc $(LIB_HSS) \
 	  --title=$(PKGNAME) \
 	  $(shell $(HADDOCK_HAS) --package-name          && echo "--package-name=$(PKGNAME)" ) \
diff --git a/src/Conjure.hs b/src/Conjure.hs
--- a/src/Conjure.hs
+++ b/src/Conjure.hs
@@ -17,18 +17,18 @@
 --
 -- Step 2: declare a list with the potential building blocks:
 --
--- > primitives :: [Prim]
--- > primitives =
--- >   [ pr (0::Int)
--- >   , pr (1::Int)
--- >   , prim "+" ((+) :: Int -> Int -> Int)
--- >   , prim "*" ((*) :: Int -> Int -> Int)
--- >   , prim "-" ((-) :: Int -> Int -> Int)
+-- > ingredients :: [Ingredient]
+-- > ingredients =
+-- >   [ con (0::Int)
+-- >   , con (1::Int)
+-- >   , fun "+" ((+) :: Int -> Int -> Int)
+-- >   , fun "*" ((*) :: Int -> Int -> Int)
+-- >   , fun "-" ((-) :: Int -> Int -> Int)
 -- >   ]
 --
 -- Step 3: call 'conjure' and see your generated function:
 --
--- > > conjure "factorial" factorial primitives
+-- > > conjure "factorial" factorial ingredients
 -- > factorial :: Int -> Int
 -- > -- 0.1s, testing 4 combinations of argument values
 -- > -- 0.8s, pruning with 27/65 rules
@@ -62,11 +62,11 @@
 -- > take' 3 [x,y]  =  [x,y]
 --
 -- > > conjure "take" (take' :: Int -> [A] -> [A])
--- > >   [ pr (0 :: Int)
--- > >   , pr (1 :: Int)
--- > >   , pr ([] :: [A])
--- > >   , prim ":" ((:) :: A -> [A] -> [A])
--- > >   , prim "-" ((-) :: Int -> Int -> Int)
+-- > >   [ con (0 :: Int)
+-- > >   , con (1 :: Int)
+-- > >   , con ([] :: [A])
+-- > >   , fun ":" ((:) :: A -> [A] -> [A])
+-- > >   , fun "-" ((-) :: Int -> Int -> Int)
 -- > >   ]
 -- > take :: Int -> [A] -> [A]
 -- > -- testing 153 combinations of argument values
@@ -80,9 +80,9 @@
 -- > take x (y:xs)  =  y:take (x - 1) xs
 --
 -- The above example also takes less than a second to run in a modern laptop.
--- The selection of functions in the list of primitives was minimized
+-- The selection of functions in the list of ingredients was minimized
 -- to what was absolutely needed here.
--- With a larger collection as primitives YMMV.
+-- With a larger collection as ingredients YMMV.
 --
 -- Conjure works for user-defined algebraic data types too,
 -- given that they are made instances of the 'Conjurable' typeclass.
@@ -94,22 +94,20 @@
   (
 -- * Basic use
     conjure
-  , Prim
-  , pr
-  , prim
+  , Ingredient
+  , con
+  , fun
   , guard
-  , prif
-  , primOrdCaseFor
+  , iif
+  , ordcase
 
--- * Advanced use
-  , conjureWithMaxSize
-  , conjureWith
-  , Args(..)
-  , args
+-- * Basic configuration parameters
+  , maxTests
+  , target
+  , maxSize
 
 -- * Conjuring from a specification
   , conjureFromSpec
-  , conjureFromSpecWith
 
 -- * When using custom types
   , Conjurable (conjureExpress, conjureEquality, conjureTiers, conjureCases, conjureSubTypes, conjureSize)
@@ -129,14 +127,46 @@
 -- * Pure interfaces
   , Results (..)
   , conjpure
-  , conjpureWith
 
 -- * Helper test types
   , A, B, C, D, E, F
+
+-- * Advanced options
+  , maxRecursions
+  , maxEquationSize
+  , maxSearchTests
+  , maxDeconstructionSize
+  , maxConstantSize
+  , maxPatternSize
+  , maxPatternDepth
+
+-- * Debug options
+  , showCandidates
+  , showTheory
+  , singlePattern
+  , showTests
+  , showPatterns
+  , showDeconstructions
+  , carryOn
+
+-- * Advanced pruning options
+  , dontRewrite
+  , dontRequireDescent
+  , omitAssortedPruning
+  , omitEarlyTests
+  , dontCopyBindings
+  , nonAtomicNumbers
+  , uniqueCandidates
+
+-- * Deprecated functions
+  , Prim
+  , pr
+  , prim
   )
 where
 
 import Conjure.Engine
 import Conjure.Conjurable
-import Conjure.Prim
+import Conjure.Ingredient
 import Conjure.Conjurable.Derive
+import Conjure.Settings
diff --git a/src/Conjure/Conjurable.hs b/src/Conjure/Conjurable.hs
--- a/src/Conjure/Conjurable.hs
+++ b/src/Conjure/Conjurable.hs
@@ -269,7 +269,7 @@
 -- | Computes a list of holes encoded as 'Expr's
 --   from a 'Conjurable' functional value.
 --
--- (cf. 'Conjure.Prim.cjHoles')
+-- (cf. 'Conjure.Ingredient.cjHoles')
 conjureHoles :: Conjurable f => f -> [Expr]
 conjureHoles f  =  [eh | (eh,_,Just _,_,_,_) <- conjureReification f]
 
diff --git a/src/Conjure/Engine.hs b/src/Conjure/Engine.hs
--- a/src/Conjure/Engine.hs
+++ b/src/Conjure/Engine.hs
@@ -11,27 +11,48 @@
 {-# LANGUAGE CPP, RecordWildCards, TupleSections #-}
 module Conjure.Engine
   ( conjure
-  , conjureWithMaxSize
-  , Args(..)
-  , args
-  , conjureWith
   , conjureFromSpec
-  , conjureFromSpecWith
   , conjure0
-  , conjure0With
   , Results(..)
   , conjpure
-  , conjpureWith
   , conjpureFromSpec
-  , conjpureFromSpecWith
   , conjpure0
-  , conjpure0With
   , candidateExprs
   , candidateDefns
-  , candidateDefns1
-  , candidateDefnsC
-  , conjureTheory
-  , conjureTheoryWith
+
+  -- * settings
+  , maxTests
+  , maxSize
+  , target
+
+  -- * Advanced settings
+  , maxRecursions
+  , maxEquationSize
+  , maxSearchTests
+  , maxDeconstructionSize
+  , maxConstantSize
+  , maxPatternSize
+  , maxPatternDepth
+
+  -- * Debug options
+  , showCandidates
+  , showTheory
+  , singlePattern
+  , showTests
+  , showPatterns
+  , showDeconstructions
+  , carryOn
+
+  -- * Pruning options
+  , dontRewrite
+  , dontRequireDescent
+  , omitAssortedPruning
+  , omitEarlyTests
+  , dontCopyBindings
+  , nonAtomicNumbers
+  , uniqueCandidates
+
+  -- * other modules
   , module Data.Express
   , module Data.Express.Fixtures
   , module Conjure.Reason
@@ -49,12 +70,13 @@
 
 import Conjure.Expr
 import Conjure.Conjurable
-import Conjure.Prim
+import Conjure.Ingredient
 import Conjure.Defn
 import Conjure.Defn.Redundancy
 import Conjure.Defn.Test
 import Conjure.Red
 import Conjure.Reason
+import Conjure.Settings
 
 import System.CPUTime (getCPUTime)
 
@@ -72,18 +94,18 @@
 -- > factorial 3  =  6
 -- > factorial 4  =  24
 -- >
--- > primitives :: [Prim]
--- > primitives =
--- >   [ pr (0::Int)
--- >   , pr (1::Int)
--- >   , prim "+" ((+) :: Int -> Int -> Int)
--- >   , prim "*" ((*) :: Int -> Int -> Int)
--- >   , prim "-" ((-) :: Int -> Int -> Int)
+-- > ingredients :: [Ingredient]
+-- > ingredients  =
+-- >   [ con (0::Int)
+-- >   , con (1::Int)
+-- >   , fun "+" ((+) :: Int -> Int -> Int)
+-- >   , fun "*" ((*) :: Int -> Int -> Int)
+-- >   , fun "-" ((-) :: Int -> Int -> Int)
 -- >   ]
 --
--- The conjure function does the following:
+-- The 'conjure' function does the following:
 --
--- > > conjure "factorial" factorial primitives
+-- > > conjure "factorial" factorial ingredients
 -- > factorial :: Int -> Int
 -- > -- 0.1s, testing 4 combinations of argument values
 -- > -- 0.8s, pruning with 27/65 rules
@@ -94,9 +116,9 @@
 -- > factorial 0  =  1
 -- > factorial x  =  x * factorial (x - 1)
 --
--- The primitives list is defined with 'pr' and 'prim'.
-conjure :: Conjurable f => String -> f -> [Prim] -> IO ()
-conjure  =  conjureWith args
+-- The ingredients list is defined with 'con' and 'fun'.
+conjure :: Conjurable f => String -> f -> [Ingredient] -> IO ()
+conjure nm f  =  conjure0 nm f (const True)
 
 
 -- | Conjures an implementation from a function specification.
@@ -113,7 +135,7 @@
 --
 -- Then:
 --
--- > > conjureFromSpec "square" squareSpec [prim "*" ((*) :: Int -> Int -> Int)]
+-- > > conjureFromSpec "square" squareSpec [fun "*" ((*) :: Int -> Int -> Int)]
 -- > square :: Int -> Int
 -- > -- 0.1s, pruning with 2/6 rules
 -- > -- 0.1s, 1 candidates of size 1
@@ -133,200 +155,92 @@
 -- >   , holds n $ \x -> square x >= 0
 -- >   , exists n $ \x -> square x > x
 -- >   ]  where  n = 60
-conjureFromSpec :: Conjurable f => String -> (f -> Bool) -> [Prim] -> IO ()
-conjureFromSpec  =  conjureFromSpecWith args
+conjureFromSpec :: Conjurable f => String -> (f -> Bool) -> [Ingredient] -> IO ()
+conjureFromSpec nm p  =  conjure0 nm undefined p
 
 
 -- | Synthesizes an implementation from both a partial definition and a
 --   function specification.
 --
 --   This works like the functions 'conjure' and 'conjureFromSpec' combined.
-conjure0 :: Conjurable f => String -> f -> (f -> Bool) -> [Prim] -> IO ()
-conjure0  =  conjure0With args
-
-
--- | Like 'conjure' but allows setting the maximum size of considered expressions
---   instead of the default value of 24.
---
--- > conjureWithMaxSize 12 "function" function [...]
---
--- This function is a candidate for going away.
--- Please set maxSize in Args instead.
-conjureWithMaxSize :: Conjurable f => Int -> String -> f -> [Prim] -> IO ()
-conjureWithMaxSize sz  =  conjureWith args
-                       {  maxSize = sz
-                       ,  maxEquationSize = min sz (maxEquationSize args)
-                       }
-
-
--- | Arguments to be passed to 'conjureWith' or 'conjpureWith'.
---   See 'args' for the defaults.
-data Args = Args
-  { maxTests              :: Int  -- ^ maximum number of tests to each candidate
-  , maxSize               :: Int  -- ^ maximum size of candidate bodies
-  , target                :: Int  -- ^ enumerate further sizes of candidates until this target
-  , maxEvalRecursions     :: Int  -- ^ maximum number of recursive evaluations when testing candidates
-  , maxEquationSize       :: Int  -- ^ maximum size of equation operands
-  , maxSearchTests        :: Int  -- ^ maximum number of tests to search for defined values
-  , maxDeconstructionSize :: Int  -- ^ maximum size of deconstructions (e.g.: @_ - 1@)
-  , maxConstantSize       :: Int  -- ^ maximum size of constants (0 for no limit)
-  , maxPatternSize        :: Int  -- ^ maximum size of patterns (0 for no limit)
-  , maxPatternDepth       :: Int  -- ^ maximum depth of patterns
-
-  -- advanced & debug options --
-  , carryOn               :: Bool -- ^ whether to carry on after finding a suitable candidate
-  , showTheory            :: Bool -- ^ show theory discovered by Speculate used in pruning
-  , usePatterns           :: Bool -- ^ use pattern matching to create (recursive) candidates
-  , showRuntime           :: Bool -- ^ show runtime
-  , showCandidates        :: Bool -- ^ (debug) show candidates -- warning: wall of text
-  , showTests             :: Bool -- ^ (debug) show tests
-  , showPatterns          :: Bool -- ^ (debug) show possible LHS patterns
-  , showDeconstructions   :: Bool -- ^ (debug) show conjectured-and-allowed deconstructions
-
-  -- pruning options --
-  , rewriting             :: Bool -- ^ unique-modulo-rewriting candidates
-  , requireDescent        :: Bool -- ^ require recursive calls to deconstruct arguments
-  , adHocRedundancy       :: Bool -- ^ ad-hoc redundancy checks
-  , copyBindings          :: Bool -- ^ copy partial definition bindings in candidates
-  , earlyTests            :: Bool -- ^ perform tests early-and-independently on each binding
-  , atomicNumbers         :: Bool -- ^ restrict constant/ground numeric expressions to atoms
-  , requireZero           :: Bool -- ^ require 0 as base case for Num recursions
-  , uniqueCandidates      :: Bool -- ^ unique-modulo-testing candidates
-  }
-
-
--- | Default arguments to conjure.
---
--- * 60 tests
--- * functions of up to 24 symbols
--- * target testing over 50400 candidates
--- * maximum of one recursive call allowed in candidate bodies
--- * maximum evaluation of up to 60 recursions
--- * pruning with equations up to size 5
--- * search for defined applications for up to 100000 combinations
--- * require recursive calls to deconstruct arguments
--- * don't show the theory used in pruning
--- * do not show tested candidates
--- * do not make candidates unique module testing
-args :: Args
-args = Args
-  { maxTests               =  360
-  , maxSize                =  24
-  , target                 =  10080
-  , maxEvalRecursions      =  60
-  , maxEquationSize        =   5
-  , maxSearchTests         =  110880
-  , maxDeconstructionSize  =   4
-  , maxConstantSize        =   0 -- unlimited
-  , maxPatternSize         =   0 -- unlimited
-  , maxPatternDepth        =   1
-
-  -- advanced & debug options --
-  , carryOn                =  False
-  , showTheory             =  False
-  , usePatterns            =  True
-  , showRuntime            =  True
-  , showCandidates         =  False
-  , showTests              =  False
-  , showDeconstructions    =  False
-  , showPatterns           =  False
-
-  -- pruning options --
-  , rewriting              =  True
-  , requireDescent         =  True
-  , adHocRedundancy        =  True
-  , copyBindings           =  True
-  , earlyTests             =  True
-  , atomicNumbers          =  True
-  , requireZero            =  False
-  , uniqueCandidates       =  False
-  }
-
--- TODO: remove the requireZero option from args?
-
-
--- | Like 'conjure' but allows setting options through 'Args'/'args'.
---
--- > conjureWith args{maxSize = 18} "function" function [...]
-conjureWith :: Conjurable f => Args -> String -> f -> [Prim] -> IO ()
-conjureWith args nm f  =  conjure0With args nm f (const True)
-
--- | Like 'conjureFromSpec' but allows setting options through 'Args'/'args'.
---
--- > conjureFromSpecWith args{maxSize = 18} "function" spec [...]
-conjureFromSpecWith :: Conjurable f => Args -> String -> (f -> Bool) -> [Prim] -> IO ()
-conjureFromSpecWith args nm p  =  conjure0With args nm undefined p
-
--- | Like 'conjure0' but allows setting options through 'Args'/'args'.
-conjure0With :: Conjurable f => Args -> String -> f -> (f -> Bool) -> [Prim] -> IO ()
-conjure0With args nm f p es  =  do
+conjure0 :: Conjurable f => String -> f -> (f -> Bool) -> [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
   -- needs to be cleaned up and simplified
-  t0 <- if showRuntime args
-        then getCPUTime
-        else return (-1)
+  t0 <- getCPUTime
   print (var (head $ words nm) f)
   when (length ts > 0) $ do
     putWithTimeSince t0 $ "testing " ++ show (length ts) ++ " combinations of argument values"
-    when (showTests args) $ do
+    when showTests $ do
       putStrLn $ "{-"
       putStr $ showDefn ts
       putStrLn $ "-}"
-  putWithTimeSince t0 $ "pruning with " ++ show nRules ++ "/" ++ show nREs ++ " rules"
-  when (showTheory args) $ do
-    putStrLn $ "{-"
-    printThy thy
-    putStrLn $ "-}"
-  when (not . null $ invalid thy) $ do
-    putStrLn $ "-- reasoning produced "
-            ++ show (length (invalid thy)) ++ " incorrect properties,"
-            ++ " please re-run with more tests for faster results"
-    when (showTheory args) $ do
+  if length ts == 0 && errorToFalse (p undefined)
+  then putStrLn $ nm ++ "  =  error \"could not reify specification, suggestion: conjureFromSpec\"\n"
+  else do
+    putWithTimeSince t0 $ "pruning with " ++ show nRules ++ "/" ++ show nREs ++ " rules"
+    when showTheory $ do
       putStrLn $ "{-"
-      putStrLn $ "invalid:"
-      putStr   $ unlines $ map showEq $ invalid thy
+      printThy thy
       putStrLn $ "-}"
-  when (showPatterns args) $ do
-    putStr $ unlines
-           $ zipWith (\i -> (("-- allowed patterns of size " ++ show i ++ "\n{-\n") ++) . (++ "-}") . unlines) [1..]
-           $ mapT showDefn
-           $ patternss results
-  when (showDeconstructions args) $ do
-    putStrLn $ "{- List of allowed deconstructions:"
-    putStr   $ unlines $ map show $ deconstructions results
-    putStrLn $ "-}"
-  pr t0 1 0 rs
+    when (not . null $ invalid thy) $ do
+      putStrLn $ "-- reasoning produced "
+              ++ show (length (invalid thy)) ++ " incorrect properties,"
+              ++ " please re-run with more tests for faster results"
+      when showTheory $ do
+        putStrLn $ "{-"
+        putStrLn $ "invalid:"
+        putStr   $ unlines $ map showEq $ invalid thy
+        putStrLn $ "-}"
+    when showPatterns $ do
+      putStr $ unlines
+             $ zipWith (\i -> (("-- allowed patterns of size " ++ show i ++ "\n{-\n") ++) . (++ "-}") . unlines) [1..]
+             $ mapT showDefn
+             $ patternss results
+    when showDeconstructions $ do
+      putStrLn $ "{- List of allowed deconstructions:"
+      putStr   $ unlines $ map show $ deconstructions results
+      putStrLn $ "-}"
+    pr t0 1 0 rs
   where
   showEq eq  =  showExpr (fst eq) ++ " == " ++ showExpr (snd eq)
   pr :: Integer -> Int -> Int -> [([Defn], [Defn])] -> IO ()
   pr t0 n t []  =  do putWithTimeSince t0 $ "tested " ++ show t ++ " candidates"
-                      putStrLn $ "cannot conjure\n"
+                      putStrLn $ nm ++ "  =  undefined  -- search exhausted\n"
   pr t0 n t ((is,cs):rs)  =  do
     let nc  =  length cs
     putWithTimeSince t0 $ show nc ++ " candidates of size " ++ show n
-    when (showCandidates args) $
+    when showCandidates $
       putStr $ unlines $ ["{-"] ++ map showDefn cs ++ ["-}"]
     case is of
       []     ->  pr t0 (n+1) (t+nc) rs
       (_:_)  ->  do pr1 t is cs
-                    when (carryOn args) $ pr t0 (n+1) (t+nc) rs
+                    when carryOn $ pr t0 (n+1) (t+nc) rs
     where
     pr1 t [] cs  =  return ()
     pr1 t (i:is) cs  =  do
       let (cs',cs'') = break (i==) cs
       let t' = t + length cs' + 1
       putWithTimeSince t0 $ "tested " ++ show t' ++ " candidates"
-      putStrLn $ showDefn i
-      when (carryOn args) $ pr1 t' is (drop 1 cs'')
+      putStrLn $ showDefn $ normalizeDefn thy i
+      when carryOn $ pr1 t' is (drop 1 cs'')
   rs  =  zip iss css
-  results  =  conjpure0With args nm f p es
+  results  =  conjpure0 nm f p es
   iss  =  implementationss results
   css  =  candidatess results
   ts   =  bindings results
   thy  =  theory results
   nRules  =  length (rules thy)
   nREs  =  length (equations thy) + nRules
+  -- we could avoid the following as most are called once
+  -- but is nice to have a summary of which settings are used
+  carryOn              =  carryOnI es
+  showTests            =  showTestsI es
+  showTheory           =  showTheoryI es
+  showPatterns         =  showPatternsI es
+  showCandidates       =  showCandidatesI es
+  showDeconstructions  =  showDeconstructionsI es
 
 
 -- | Results to the 'conjpure' family of functions.
@@ -346,33 +260,19 @@
 --
 -- 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 -> [Prim] -> Results
-conjpure =  conjpureWith args
+conjpure :: Conjurable f => String -> f -> [Ingredient] -> Results
+conjpure nm f  =  conjpure0 nm f (const True)
 
 -- | Like 'conjureFromSpec' but in the pure world.  (cf. 'conjpure')
-conjpureFromSpec :: Conjurable f => String -> (f -> Bool) -> [Prim] -> Results
-conjpureFromSpec  =  conjpureFromSpecWith args
-
--- | Like 'conjure0' but in the pure world.  (cf. 'conjpure')
-conjpure0 :: Conjurable f => String -> f -> (f -> Bool) -> [Prim] -> Results
-conjpure0 =  conjpure0With args
-
--- | Like 'conjpure' but allows setting options through 'Args' and 'args'.
-conjpureWith :: Conjurable f => Args -> String -> f -> [Prim] -> Results
-conjpureWith args nm f  =  conjpure0With args nm f (const True)
-
--- | Like 'conjureFromSpecWith' but in the pure world.  (cf. 'conjpure')
-conjpureFromSpecWith :: Conjurable f => Args -> String -> (f -> Bool) -> [Prim] -> Results
-conjpureFromSpecWith args nm p  =  conjpure0With args nm undefined p
+conjpureFromSpec :: Conjurable f => String -> (f -> Bool) -> [Ingredient] -> Results
+conjpureFromSpec nm p  =  conjpure0 nm undefined p
 
--- | Like 'conjpure0' but allows setting options through 'Args' and 'args'.
---
--- This is where the actual implementation resides.  The functions
--- 'conjpure', 'conjpureWith', 'conjpureFromSpec', 'conjpureFromSpecWith',
--- 'conjure', 'conjureWith', 'conjureFromSpec', 'conjureFromSpecWith' and
--- 'conjure0' all refer to this.
-conjpure0With :: Conjurable f => Args -> String -> f -> (f -> Bool) -> [Prim] -> Results
-conjpure0With args@(Args{..}) nm f p es  =  Results
+-- | 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 nm f p es  =  Results
   { implementationss  =  implementationsT
   , candidatess  =  candidatesT
   , bindings  =  tests
@@ -384,33 +284,22 @@
   implementationsT  =  filterT implements candidatesT
   implements fx  =  defnApparentlyTerminates fx
                  && test fx
-                 && errorToFalse (p (cevl maxEvalRecursions fx))
-  candidatesT  =  (if uniqueCandidates then nubCandidates args nm f else id)
+                 && errorToFalse (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)
                $  candidatesTT
-  (candidatesTT, thy, patternss, deconstructions)  =  candidateDefns args nm f es
+  (candidatesTT, thy, patternss, deconstructions)  =  candidateDefns nm f es
 
-  test dfn  =  all (errorToFalse . deval (conjureExpress f) maxEvalRecursions dfn False)
+  test dfn  =  all (errorToFalse . deval (conjureExpress f) maxRecursions dfn False)
             $  [funToVar lhs -==- rhs | (lhs, rhs) <- tests]
   tests  =  conjureTestDefn maxTests maxSearchTests nm f
   (-==-)  =  conjureMkEquation f
-
-
--- | Just prints the underlying theory found by "Test.Speculate"
---   without actually synthesizing a function.
-conjureTheory :: Conjurable f => String -> f -> [Prim] -> IO ()
-conjureTheory  =  conjureTheoryWith args
-
-
--- | Like 'conjureTheory' but allows setting options through 'Args'/'args'.
-conjureTheoryWith :: Conjurable f => Args -> String -> f -> [Prim] -> IO ()
-conjureTheoryWith args nm f es  =  do
-  putStrLn $ "theory with " ++ (show . length $ rules thy) ++ " rules and "
-                            ++ (show . length $ equations thy) ++ " equations"
-  printThy thy
-  where
-  Results {theory = thy}  =  conjpureWith args nm f es
+  maxTests  =  maxTestsI es
+  (target, maxSize)  =  targetAndMaxSizeI es
+  maxRecursions  =  maxRecursionsI es
+  maxSearchTests  =  maxSearchTestsI es
+  uniqueCandidates  =  uniqueCandidatesI es
 
 
 -- | Return apparently unique candidate definitions.
@@ -420,18 +309,18 @@
 -- 1. tiers of candidate definitions
 -- 2. an equational theory
 -- 3. a list of allowed deconstructions
-candidateDefns :: Conjurable f => Args -> String -> f -> [Prim] -> ([[Defn]], Thy, [[Defn]], [Expr])
-candidateDefns args  =  candidateDefns' args
+candidateDefns :: Conjurable f => String -> f -> [Ingredient] -> ([[Defn]], Thy, [[Defn]], [Expr])
+candidateDefns nm f is  =  candidateDefns' nm f is
   where
-  candidateDefns'  =  if usePatterns args
-                      then candidateDefnsC
-                      else candidateDefns1
+  candidateDefns'  =  if singlePatternI is
+                      then candidateDefns1
+                      else candidateDefnsC
 
 
 -- | Return apparently unique candidate definitions
 --   where there is a single body.
-candidateDefns1 :: Conjurable f => Args -> String -> f -> [Prim] -> ([[Defn]], Thy, [[Defn]], [Expr])
-candidateDefns1 args nm f ps  =  first4 (mapT toDefn) $ candidateExprs args nm f ps
+candidateDefns1 :: Conjurable f => String -> f -> [Ingredient] -> ([[Defn]], Thy, [[Defn]], [Expr])
+candidateDefns1 nm f ps  =  first4 (mapT toDefn) $ candidateExprs nm f ps
   where
   efxs  =  conjureVarApplication nm f
   toDefn e  =  [(efxs, e)]
@@ -439,14 +328,15 @@
 
 
 -- | Return apparently unique candidate bodies.
-candidateExprs :: Conjurable f => Args -> String -> f -> [Prim] -> ([[Expr]], Thy, [[Defn]], [Expr])
-candidateExprs Args{..} nm f ps  =
+candidateExprs :: Conjurable f => String -> f -> [Ingredient] -> ([[Expr]], Thy, [[Defn]], [Expr])
+candidateExprs nm f is  =
   ( as \/ concatMapT (`enumerateFillings` recs) ts
   , thy
   , [[ [(efxs, eh)] ]]
   , deconstructions
   )
   where
+  ps  =  actual is  -- extract actual primitives
   es  =  map fst ps
   ts | typ efxs == boolTy  =  foldAppProducts andE [cs, rs]
                            \/ foldAppProducts orE  [cs, rs]
@@ -463,7 +353,7 @@
   eh  =  holeAsTypeOf efxs
   efxs  =  conjureVarApplication nm f
   (ef:exs)  =  unfoldApp efxs
-  keep | rewriting  =  isRootNormalC thy . fastMostGeneralVariation
+  keep | rewrite    =  isRootNormalC thy . fastMostGeneralVariation
        | otherwise  =  const True
   keepR | requireDescent  =  descends isDecOf efxs
         | otherwise       =  const True
@@ -487,14 +377,19 @@
         $  foldAppProducts ef [forN h | h <- conjureArgumentHoles f]
   thy  =  doubleCheck (===)
        .  theoryFromAtoms (===) maxEquationSize . (:[]) . nub
-       $  cjHoles (prim nm f:ps) ++ [val False, val True] ++ es
-  (===)  =  cjAreEqual (prim nm f:ps) maxTests
+       $  cjHoles (fun nm f:ps) ++ [val False, val True] ++ es
+  (===)  =  cjAreEqual (fun nm f:ps) maxTests
+  maxTests               =  maxTestsI is
+  maxEquationSize        =  maxEquationSizeI is
+  maxDeconstructionSize  =  maxDeconstructionSizeI is
+  requireDescent         =  requireDescentI is
+  rewrite                =  rewriteI is
 
 
 -- | Return apparently unique candidate definitions
 --   using pattern matching.
-candidateDefnsC :: Conjurable f => Args -> String -> f -> [Prim] -> ([[Defn]], Thy, [[Defn]], [Expr])
-candidateDefnsC Args{..} nm f ps  =
+candidateDefnsC :: Conjurable f => String -> f -> [Ingredient] -> ([[Defn]], Thy, [[Defn]], [Expr])
+candidateDefnsC nm f is =
   ( discardT hasRedundant $ concatMapT fillingsFor fss
   , thy
   , mapT (map (,eh)) pats
@@ -505,6 +400,7 @@
        | otherwise           =                        conjurePats maxPatternDepth es nm f
   fss  =  concatMapT ps2fss pats
   -- replaces the any guard symbol with a guard of the correct type
+  ps  =  actual is  -- extract actual ingredients/primitives from the list
   es  =  [if isGuardSymbol e then conjureGuard f else e | (e,_) <- ps]
 
   eh  =  holeAsTypeOf efxs
@@ -577,7 +473,6 @@
       -- numeric arguments additionally require 0 to be present as a case
       -- for recursion
       should aes ae  =  length (nub aes) > 1 && hasVar ae && (isApp ae || isUnbreakable ae)
-                     && (not requireZero || not (isNumeric ae) || any isZero aes)
       aes   =                  (tail . unfoldApp . rehole) pat
       aess  =  transpose $ map (tail . unfoldApp . rehole) pats
 
@@ -644,11 +539,25 @@
 
   thy  =  doubleCheck (===)
        .  theoryFromAtoms (===) maxEquationSize . (:[]) . nub
-       $  cjHoles (prim nm f:ps) ++ [val False, val True] ++ es
-  (===)  =  cjAreEqual (prim nm f:ps) maxTests
+       $  cjHoles (fun nm f:ps) ++ [val False, val True] ++ es
+  (===)  =  cjAreEqual (fun nm f:ps) maxTests
   isUnbreakable  =  conjureIsUnbreakable f
 
+  maxTests               =  maxTestsI is
+  maxSearchTests         =  maxSearchTestsI is
+  maxEquationSize        =  maxEquationSizeI is
+  maxConstantSize        =  maxConstantSizeI is
+  maxDeconstructionSize  =  maxDeconstructionSizeI is
+  maxPatternDepth        =  maxPatternDepthI is
+  maxPatternSize         =  maxPatternSizeI is
+  requireDescent         =  requireDescentI is
+  earlyTests             =  earlyTestsI is
+  copyBindings           =  copyBindingsI is
+  adHocRedundancy        =  assortedPruningI is -- TODO: rename
+  atomicNumbers          =  atomicNumbersI is
+  rewriting              =  rewriteI is
 
+
 -- | Checks if the given pattern is a ground pattern.
 --
 -- A pattern is a ground pattern when its arguments are fully defined
@@ -706,9 +615,9 @@
 
 -- equality between candidates
 
-nubCandidates :: Conjurable f => Args -> String -> f -> [[Defn]] -> [[Defn]]
-nubCandidates Args{..} nm f  =
-  discardLaterT $ equalModuloTesting maxTests maxEvalRecursions nm f
+nubCandidates :: Conjurable f => Int -> Int -> String -> f -> [[Defn]] -> [[Defn]]
+nubCandidates maxTests maxRecursions nm f  =
+  discardLaterT $ equalModuloTesting maxTests maxRecursions nm f
 
 
 --- tiers utils ---
@@ -751,6 +660,26 @@
   | n <= 0     =  []
   | otherwise  =  case xss of [] -> []
                               (xs:xss) -> xs : targetiers (n - length xs) xss
+
+normalizeDefn :: Thy -> Defn -> Defn
+normalizeDefn  =  map . normalizeBndn
+
+-- This function is quite expensive to run with bad complexity,
+-- but is fine on Conjure: candidates are at most a few dozen symbols long
+-- and this function just runs once.
+normalizeBndn :: Thy -> Bndn -> Bndn
+normalizeBndn thy (lhs, rhs)
+  | ef `elem` vars rhs  =  (lhs, mapInnerFirstOuterLast commutsort rhs)
+  | otherwise           =  (lhs, rhs)
+  where
+  ef:_  =  unfoldApp lhs
+  -- recursive calls come later in this ordering
+  commutsort (eo :$ ex :$ ey)
+    | isCommutative thy eo  =  if (ef `elem` vars ex, ex)
+                               <= (ef `elem` vars ey, ey)
+                               then eo :$ ex :$ ey
+                               else eo :$ ey :$ ex
+  commutsort e  =  e
 
 boolTy :: TypeRep
 boolTy  =  typ b_
diff --git a/src/Conjure/Expr.hs b/src/Conjure/Expr.hs
--- a/src/Conjure/Expr.hs
+++ b/src/Conjure/Expr.hs
@@ -39,6 +39,7 @@
   , isGuardSymbol
   , isGuard
   , hasGuard
+  , mapInnerFirstOuterLast
 
   , enumerateAppsFor
   , enumerateFillings
@@ -352,14 +353,15 @@
 
 -- -- Expression enumeration -- --
 
--- | Enumerate applications between values of the given list of primitives
---   and of the given expressions's type.
+-- | Enumerate applications between values of
+--   the given list of atomic expressions
+--   and of the given resulting expressions's type.
 --
 -- __Arguments:__
 --
 -- 1. an 'Expr' whose type we are interested in
 -- 2. a filtering function, returning 'True' for the expressions to keep
--- 3. a list of primitives to be used in building expression.
+-- 3. a list of atomic expressions to be used in building expression.
 --
 -- __Result:__ a potentially infinite list of list of enumerated expressions
 --
@@ -628,6 +630,16 @@
 isStrictSubexprOf :: Expr -> Expr -> Bool
 isStrictSubexprOf e1 e2  =  e1 /= e2
                          && e1 `isSubexprOf` e2
+
+-- TODO: move mapInner to Express?
+--       of course with a shorter name.
+--
+-- The long name here is intentional to prevent a future clash.  :-)
+mapInnerFirstOuterLast :: (Expr -> Expr) -> Expr -> Expr
+mapInnerFirstOuterLast f  =  m
+  where
+  m (ef :$ ex)  =  f (m ef :$ m ex)
+  m e  =  f e
 
 instance Express A where  expr  =  val
 instance Express B where  expr  =  val
diff --git a/src/Conjure/Ingredient.hs b/src/Conjure/Ingredient.hs
new file mode 100644
--- /dev/null
+++ b/src/Conjure/Ingredient.hs
@@ -0,0 +1,275 @@
+-- |
+-- Module      : Conjure.Ingredient
+-- Copyright   : (c) 2021-2025 Rudy Matela
+-- License     : 3-Clause BSD  (see the file LICENSE)
+-- Maintainer  : Rudy Matela <rudy@matela.com.br>
+--
+-- This module is part of "Conjure".
+--
+-- The 'Ingredient' type and utilities involving it.
+--
+-- You are probably better off importing "Conjure".
+module Conjure.Ingredient
+  ( Ingredient
+  , con
+  , fun
+  , iif
+  , ordcase
+  , guard
+  , cjHoles
+  , cjTiersFor
+  , cjAreEqual
+  , cjMkEquation
+  , Prim
+  , pr
+  , prim
+  , prif
+  , primOrdCaseFor
+  )
+where
+
+import Conjure.Conjurable
+import Conjure.Expr
+import Test.LeanCheck.Error (errorToFalse)
+import Test.LeanCheck.Utils
+
+
+-- | A single functional ingredient in conjuring.
+-- Specify conjure ingredients with 'con' and 'fun':
+--
+-- > conjure "foo" foo [ con False
+-- >                   , con True
+-- >                   , con (0 :: Int)
+-- >                   , con (1 :: Int)
+-- >                   , ...
+-- >                   , fun "&&" (&&)
+-- >                   , fun "||" (||)
+-- >                   , fun "+" ((+) :: Int -> Int -> Int)
+-- >                   , fun "*" ((*) :: Int -> Int -> Int)
+-- >                   , fun "-" ((-) :: Int -> Int -> Int)
+-- >                   , ...
+-- >                   ]
+--
+-- Ingredients may include arbitrary
+-- constants ('con'),
+-- constructors ('con')
+-- or functions ('fun').
+-- These may be built-in or user defined.
+-- Use 'con' on 'Show' instances
+-- and 'fun' otherwise.
+--
+-- This is internally
+-- an arbitrary atomic 'Expr'ession
+-- paired with
+-- a 'Reification' of type information.
+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)
+
+
+-- | Provides a functional value as an ingredient to Conjure.
+--   To be used on values that are not 'Show' instances
+--   such as functions.
+--   (cf. 'con')
+--
+-- > conjure "foo" foo [ ...
+-- >                   , fun "&&" (&&)
+-- >                   , fun "||" (||)
+-- >                   , fun "+" ((+) :: Int -> Int -> Int)
+-- >                   , fun "*" ((*) :: Int -> Int -> Int)
+-- >                   , fun "-" ((-) :: Int -> Int -> Int)
+-- >                   , ...
+-- >                   ]
+--
+-- Argument types have to be monomorphized,
+-- so use type bindings when applicable.
+fun :: Conjurable a => String -> a -> Ingredient
+fun s x  =  (value s x, conjureType x)
+
+
+-- | Provides an if condition bound to the given return type
+--   as a Conjure ingredient.
+--
+-- This should be used when one wants Conjure to consider
+-- if-expressions at all:
+--
+-- > last' :: [Int] -> Int
+-- > last' [x]  =  x
+-- > last' [x,y]  =  y
+-- > last' [x,y,z]  =  z
+--
+-- > > conjure "last" last' [ con ([] :: [Int])
+-- > >                      , fun ":" ((:) :: Int -> [Int] -> [Int])
+-- > >                      , fun "null" (null :: [Int] -> Bool)
+-- > >                      , iif (undefined :: Int)
+-- > >                      , fun "undefined" (undefined :: Int)
+-- > >                      ]
+-- > last :: [Int] -> Int
+-- > -- 0.0s, testing 360 combinations of argument values
+-- > -- 0.0s, pruning with 5/5 rules
+-- > -- ...   ...   ...   ...   ...
+-- > -- 0.0s, 4 candidates of size 7
+-- > -- 0.0s, tested 2 candidates
+-- > last []  =  undefined
+-- > last (x:xs)  =  if null xs
+-- >                 then x
+-- >                 else last xs
+iif :: Conjurable a => a -> Ingredient
+iif x  =  (ifFor x, conjureType x)
+
+
+-- | Provides a guard bound to the conjured function's return type.
+--
+-- Guards are only alllowed at the root fo the RHS.
+--
+-- > last' :: [Int] -> Int
+-- > last' [x]  =  x
+-- > last' [x,y]  =  y
+-- > last' [x,y,z]  =  z
+--
+-- > > conjure "last" last'
+-- > >   [ con ([] :: [Int])
+-- > >   , fun ":" ((:) :: Int -> [Int] -> [Int])
+-- > >   , fun "null" (null :: [Int] -> Bool)
+-- > >   , guard
+-- > >   , fun "undefined" (undefined :: Int)
+-- > >   ]
+-- > last :: [Int] -> Int
+-- > -- 0.0s, testing 360 combinations of argument values
+-- > -- 0.0s, pruning with 5/5 rules
+-- > -- 0.0s, 1 candidates of size 1
+-- > -- 0.0s, 0 candidates of size 2
+-- > -- 0.0s, 0 candidates of size 3
+-- > -- 0.0s, 0 candidates of size 4
+-- > -- 0.0s, 0 candidates of size 5
+-- > -- 0.0s, 0 candidates of size 6
+-- > -- 0.0s, 4 candidates of size 7
+-- > -- 0.0s, tested 2 candidates
+-- > last []  =  undefined
+-- > last (x:xs)
+-- >   | null xs  =  x
+-- >   | otherwise  =  last xs
+guard :: Ingredient
+guard  =  (guardFor (undefined :: Bool), conjureType (undefined :: Bool))
+-- internally we always return a guard of the Bool return type,
+-- this is replaced by Conjure when enumerating candidates
+
+
+-- | Provides a case condition bound to the given return type.
+--
+-- This should be used when one wants Conjure to consider ord-case expressions:
+--
+-- > > conjure "mem" mem
+-- > >   [ con False
+-- > >   , con True
+-- > >   , fun "`compare`" (compare :: Int -> Int -> Ordering)
+-- > >   , ordcase (undefined :: Bool)
+-- > >   ]
+-- > mem :: Int -> Tree -> Bool
+-- > -- ...   ...   ...   ...   ...
+-- > -- 0.0s, 384 candidates of size 12
+-- > -- 0.0s, tested 346 candidates
+-- > mem x Leaf  =  False
+-- > mem x (Node t1 y t2)  =  case x `compare` y of
+-- >                          LT -> mem x t1
+-- >                          EQ -> True
+-- >                          GT -> mem x t2
+ordcase :: Conjurable a => a -> Ingredient
+ordcase x  =  (caseForOrd x, conjureType x)
+
+
+-- the following functions mirror their "conjure" counterparts from
+-- Conjure.Conjurable but need a list of Ingredients instead of a Conjurable
+-- representative.
+
+-- | Computes a list of 'Reification1's from a list of 'Ingredient's.
+--
+-- This function mirrors functionality of 'conjureReification'.
+cjReification :: [Ingredient] -> [Reification1]
+cjReification ps  =  nubOn (\(eh,_,_,_,_,_) -> eh)
+                  $  foldr (.) id (map snd ps) [conjureReification1 bool]
+
+-- | Computes a list of holes encoded as 'Expr's from a list of 'Ingredient's.
+--
+-- This function mirrors functionality from 'conjureHoles'.
+cjHoles :: [Ingredient] -> [Expr]
+cjHoles ps  =  [eh | (eh,_,Just _,_,_,_) <- cjReification ps]
+
+-- | Computes a function that equates two 'Expr's from a list of 'Ingredient's.
+--
+-- This function mirrors functionality from 'conjureMkEquation'.
+cjMkEquation :: [Ingredient] -> Expr -> Expr -> Expr
+cjMkEquation ps  =  mkEquation [eq | (_,Just eq,_,_,_,_) <- cjReification ps]
+
+-- | Given a list of 'Ingredient's,
+--   computes a function that checks whether two 'Expr's are equal
+--   up to a given number of tests.
+cjAreEqual :: [Ingredient] -> Int -> Expr -> Expr -> Bool
+cjAreEqual ps maxTests  =  (===)
+  where
+  (-==-)  =  cjMkEquation ps
+  e1 === e2  =  isTrue $ e1 -==- e2
+  isTrue  =  all (errorToFalse . eval False) . gs
+  gs  =  take maxTests . cjGrounds ps
+
+-- | Given a list of 'Ingredient's,
+--   computes a grounds function that lists
+--   ground expressions of an 'Expr'.
+cjGrounds :: [Ingredient] -> Expr -> [Expr]
+cjGrounds  =  grounds . cjTiersFor
+
+-- | Given a list of 'Ingredient's,
+--   returns a function that given an 'Expr'
+--   will return tiers of test 'Expr' values.
+--
+-- This is used in 'cjAreEqual'.
+cjTiersFor :: [Ingredient] -> Expr -> [[Expr]]
+cjTiersFor ps e  =  tf allTiers
+  where
+  allTiers :: [ [[Expr]] ]
+  allTiers  =  [etiers | (_,_,Just etiers,_,_,_) <- cjReification ps]
+  tf []  =  [[e]] -- no tiers found, keep variable
+  tf (etiers:etc)  =  case etiers of
+                      ((e':_):_) | typ e' == typ e -> etiers
+                      _                            -> tf etc
+
+
+
+
+-- | __DEPRACATED__.  Please use 'Ingredient' instead
+type Prim  =  Ingredient
+{-# DEPRECATED Prim "'Prim' is deprecated, please use 'Ingredient' instead" #-}
+
+
+-- | __DEPRECATED__.  Please use 'con' instead.
+pr :: (Conjurable a, Show a) => a -> Ingredient
+pr  =  con
+{-# DEPRECATED pr "'pr' is deprecated, please use 'con' instead" #-}
+
+-- | __DEPRECATED__.  Please use 'fun' instead.
+prim :: Conjurable a => String -> a -> Ingredient
+prim  =  fun
+{-# DEPRECATED prim "'prim' is deprecated, please use 'fun' instead" #-}
+
+prif :: Conjurable a => a -> Ingredient
+prif  =  iif
+{-# DEPRECATED prif "'prif' is deprecated, please use 'iif' instead" #-}
+
+primOrdCaseFor :: Conjurable a => a -> Ingredient
+primOrdCaseFor  =  ordcase
+{-# DEPRECATED primOrdCaseFor "'primOrdCaseFor' is deprecated, please use 'ordcase' instead" #-}
diff --git a/src/Conjure/Prim.hs b/src/Conjure/Prim.hs
deleted file mode 100644
--- a/src/Conjure/Prim.hs
+++ /dev/null
@@ -1,217 +0,0 @@
--- |
--- Module      : Conjure.Prim
--- Copyright   : (c) 2021-2025 Rudy Matela
--- License     : 3-Clause BSD  (see the file LICENSE)
--- Maintainer  : Rudy Matela <rudy@matela.com.br>
---
--- This module is part of "Conjure".
---
--- The 'Prim' type and utilities involving it.
---
--- You are probably better off importing "Conjure".
-module Conjure.Prim
-  ( Prim
-  , prim
-  , pr
-  , prif
-  , primOrdCaseFor
-  , guard
-  , cjHoles
-  , cjTiersFor
-  , cjAreEqual
-  , cjMkEquation
-  )
-where
-
-import Conjure.Conjurable
-import Conjure.Expr
-import Test.LeanCheck.Error (errorToFalse)
-import Test.LeanCheck.Utils
-
-
--- | A primitive expression (paired with instance reification).
---   Create 'Prim's with 'pr' and 'prim'.
-type Prim  =  (Expr, Reification)
-
-
--- | Provides a primitive value to Conjure.
---   To be used on 'Show' instances.
---   (cf. 'prim')
---
--- > conjure "fun" fun [ pr False
--- >                   , pr True
--- >                   , pr (0 :: Int)
--- >                   , pr (1 :: Int)
--- >                   , ...
--- >                   ]
---
--- Argument types have to be monomorphized,
--- so use type bindings when applicable.
-pr :: (Conjurable a, Show a) => a -> Prim
-pr x  =  (val x, conjureType x)
-
-
--- | Provides a primitive value to Conjure.
---   To be used on values that are not 'Show' instances
---   such as functions.
---   (cf. 'pr')
---
--- > conjure "fun" fun [ ...
--- >                   , prim "&&" (&&)
--- >                   , prim "||" (||)
--- >                   , prim "+" ((+) :: Int -> Int -> Int)
--- >                   , prim "*" ((*) :: Int -> Int -> Int)
--- >                   , prim "-" ((-) :: Int -> Int -> Int)
--- >                   , ...
--- >                   ]
---
--- Argument types have to be monomorphized,
--- so use type bindings when applicable.
-prim :: Conjurable a => String -> a -> Prim
-prim s x  =  (value s x, conjureType x)
-
-
--- | Provides an if condition bound to the given return type.
---
--- This should be used when one wants Conjure to consider
--- if-expressions at all:
---
--- > last' :: [Int] -> Int
--- > last' [x]  =  x
--- > last' [x,y]  =  y
--- > last' [x,y,z]  =  z
---
--- > > conjure "last" last' [ pr ([] :: [Int])
--- > >                      , prim ":" ((:) :: Int -> [Int] -> [Int])
--- > >                      , prim "null" (null :: [Int] -> Bool)
--- > >                      , prif (undefined :: Int)
--- > >                      , prim "undefined" (undefined :: Int)
--- > >                      ]
--- > last :: [Int] -> Int
--- > -- 0.0s, testing 360 combinations of argument values
--- > -- 0.0s, pruning with 5/5 rules
--- > -- ...   ...   ...   ...   ...
--- > -- 0.0s, 4 candidates of size 7
--- > -- 0.0s, tested 2 candidates
--- > last []  =  undefined
--- > last (x:xs)  =  if null xs
--- >                 then x
--- >                 else last xs
-prif :: Conjurable a => a -> Prim
-prif x  =  (ifFor x, conjureType x)
-
-
--- | Provides an if condition bound to the conjured function's return type.
---
--- Guards are only alllowed at the root fo the RHS.
---
--- > last' :: [Int] -> Int
--- > last' [x]  =  x
--- > last' [x,y]  =  y
--- > last' [x,y,z]  =  z
---
--- > > conjure "last" last'
--- > >   [ pr ([] :: [Int])
--- > >   , prim ":" ((:) :: Int -> [Int] -> [Int])
--- > >   , prim "null" (null :: [Int] -> Bool)
--- > >   , guard
--- > >   , prim "undefined" (undefined :: Int)
--- > >   ]
--- > last :: [Int] -> Int
--- > -- 0.0s, testing 360 combinations of argument values
--- > -- 0.0s, pruning with 5/5 rules
--- > -- 0.0s, 1 candidates of size 1
--- > -- 0.0s, 0 candidates of size 2
--- > -- 0.0s, 0 candidates of size 3
--- > -- 0.0s, 0 candidates of size 4
--- > -- 0.0s, 0 candidates of size 5
--- > -- 0.0s, 0 candidates of size 6
--- > -- 0.0s, 4 candidates of size 7
--- > -- 0.0s, tested 2 candidates
--- > last []  =  undefined
--- > last (x:xs)
--- >   | null xs  =  x
--- >   | otherwise  =  last xs
-guard :: Prim
-guard  =  (guardFor (undefined :: Bool), conjureType (undefined :: Bool))
--- internally we always return a guard of the Bool return type,
--- this is replaced by Conjure when enumerating candidates
-
-
--- | Provides a case condition bound to the given return type.
---
--- This should be used when one wants Conjure to consider ord-case expressions:
---
--- > > conjure "mem" mem
--- > >   [ pr False
--- > >   , pr True
--- > >   , prim "`compare`" (compare :: Int -> Int -> Ordering)
--- > >   , primOrdCaseFor (undefined :: Bool)
--- > >   ]
--- > mem :: Int -> Tree -> Bool
--- > -- ...   ...   ...   ...   ...
--- > -- 0.0s, 384 candidates of size 12
--- > -- 0.0s, tested 346 candidates
--- > mem x Leaf  =  False
--- > mem x (Node t1 y t2)  =  case x `compare` y of
--- >                          LT -> mem x t1
--- >                          EQ -> True
--- >                          GT -> mem x t2
-primOrdCaseFor :: Conjurable a => a -> Prim
-primOrdCaseFor x  =  (caseForOrd x, conjureType x)
-
-
--- the following functions mirror their "conjure" counterparts from
--- Conjure.Conjurable but need a list of Prims instead of a Conjurable
--- representative.
-
--- | Computes a list of 'Reification1's from a list of 'Prim's.
---
--- This function mirrors functionality of 'conjureReification'.
-cjReification :: [Prim] -> [Reification1]
-cjReification ps  =  nubOn (\(eh,_,_,_,_,_) -> eh)
-                  $  foldr (.) id (map snd ps) [conjureReification1 bool]
-
--- | Computes a list of holes encoded as 'Expr's from a list of 'Prim's.
---
--- This function mirrors functionality from 'conjureHoles'.
-cjHoles :: [Prim] -> [Expr]
-cjHoles ps  =  [eh | (eh,_,Just _,_,_,_) <- cjReification ps]
-
--- | Computes a function that equates two 'Expr's from a list of 'Prim's.
---
--- This function mirrors functionality from 'conjureMkEquation'.
-cjMkEquation :: [Prim] -> Expr -> Expr -> Expr
-cjMkEquation ps  =  mkEquation [eq | (_,Just eq,_,_,_,_) <- cjReification ps]
-
--- | Given a list of 'Prim's,
---   computes a function that checks whether two 'Expr's are equal
---   up to a given number of tests.
-cjAreEqual :: [Prim] -> Int -> Expr -> Expr -> Bool
-cjAreEqual ps maxTests  =  (===)
-  where
-  (-==-)  =  cjMkEquation ps
-  e1 === e2  =  isTrue $ e1 -==- e2
-  isTrue  =  all (errorToFalse . eval False) . gs
-  gs  =  take maxTests . cjGrounds ps
-
--- | Given a list of 'Prim's,
---   computes a grounds function that lists
---   ground expressions of an 'Expr'.
-cjGrounds :: [Prim] -> Expr -> [Expr]
-cjGrounds  =  grounds . cjTiersFor
-
--- | Given a list of 'Prim's,
---   returns a function that given an 'Expr'
---   will return tiers of test 'Expr' values.
---
--- This is used in 'cjAreEqual'.
-cjTiersFor :: [Prim] -> Expr -> [[Expr]]
-cjTiersFor ps e  =  tf allTiers
-  where
-  allTiers :: [ [[Expr]] ]
-  allTiers  =  [etiers | (_,_,Just etiers,_,_,_) <- cjReification ps]
-  tf []  =  [[e]] -- no tiers found, keep variable
-  tf (etiers:etc)  =  case etiers of
-                      ((e':_):_) | typ e' == typ e -> etiers
-                      _                            -> tf etc
diff --git a/src/Conjure/Settings.hs b/src/Conjure/Settings.hs
new file mode 100644
--- /dev/null
+++ b/src/Conjure/Settings.hs
@@ -0,0 +1,424 @@
+-- |
+-- Module      : Conjure.Settings
+-- Copyright   : (c) 2021-2025 Rudy Matela
+-- License     : 3-Clause BSD  (see the file LICENSE)
+-- Maintainer  : Rudy Matela <rudy@matela.com.br>
+--
+-- An internal module of "Conjure",
+-- a library for Conjuring function implementations
+-- from tests or partial definitions.
+-- (a.k.a.: functional inductive programming)
+--
+-- This contains the settings for functions in "Conjure.Engine".
+{-# LANGUAGE CPP, RecordWildCards, TupleSections #-}
+module Conjure.Settings
+  (
+  -- * Basic settings
+    maxTests
+  , maxSize
+  , target
+
+  -- * Advanced settings
+  , maxRecursions
+  , maxEquationSize
+  , maxSearchTests
+  , maxDeconstructionSize
+  , maxConstantSize
+  , maxPatternSize
+  , maxPatternDepth
+
+  -- * Debug options
+  , showCandidates
+  , showTheory
+  , singlePattern
+  , showTests
+  , showPatterns
+  , showDeconstructions
+  , carryOn
+
+  -- * Pruning options
+  , dontRewrite
+  , dontRequireDescent
+  , omitAssortedPruning
+  , omitEarlyTests
+  , dontCopyBindings
+  , nonAtomicNumbers
+  , uniqueCandidates
+
+  -- * Filtering settings
+  , actual
+
+  -- * Read basic settings
+  , maxTestsI
+  , targetAndMaxSizeI
+
+  -- * Read advanced settings
+  , maxRecursionsI
+  , maxEquationSizeI
+  , maxSearchTestsI
+  , maxDeconstructionSizeI
+  , maxConstantSizeI
+  , maxPatternSizeI
+  , maxPatternDepthI
+
+  -- * Read debug options
+  , showCandidatesI
+  , showTheoryI
+  , singlePatternI
+  , showTestsI
+  , showPatternsI
+  , showDeconstructionsI
+  , carryOnI
+
+  -- * Read pruning options
+  , rewriteI
+  , requireDescentI
+  , assortedPruningI
+  , earlyTestsI
+  , copyBindingsI
+  , atomicNumbersI
+  , uniqueCandidatesI
+  )
+where
+
+
+import Conjure.Utils
+import Data.Express (val, eval, typ)
+import Conjure.Ingredient (Ingredient)
+
+
+-- | Arguments to be passed to
+--   'Conjure.conjureWith' or 'Conjure.conjpureWith'.
+--   You should use smart constructors instead.
+data Setting
+  = Noop                       -- ^ internal use: no-op setting
+
+  | MaxTests              Int  -- ^ maximum number of tests to each candidate
+  | MaxSize               Int  -- ^ maximum size of candidate bodies
+  | Target                Int  -- ^ enumerate further sizes of candidates until this target
+  | MaxRecursions         Int  -- ^ maximum number of recursive evaluations when testing candidates
+  | MaxEquationSize       Int  -- ^ maximum size of equation operands
+  | MaxSearchTests        Int  -- ^ maximum number of tests to search for defined values
+  | MaxDeconstructionSize Int  -- ^ maximum size of deconstructions (e.g.: @- 1@)
+  | MaxConstantSize       Int  -- ^ maximum size of constants (0 for no limit)
+  | MaxPatternSize        Int  -- ^ maximum size of patterns (0 for no limit)
+  | MaxPatternDepth       Int  -- ^ maximum depth of patterns
+
+  -- advanced & debug options --
+  | CarryOn              -- ^ carry on after finding a suitable candidate
+  | ShowTheory           -- ^ show theory discovered by Speculate used in pruning
+  | SinglePattern        -- ^ restrict candidates to a single pattern
+  | ShowCandidates       -- ^ (debug) show candidates -- warning: wall of text
+  | ShowTests            -- ^ (debug) show tests
+  | ShowPatterns         -- ^ (debug) show possible LHS patterns
+  | ShowDeconstructions  -- ^ (debug) show conjectured-and-allowed deconstructions
+
+  -- pruning options --
+  | DontRewrite          -- ^ turns off unique-modulo-rewriting candidates
+  | DontRequireDescent   -- ^ require recursive calls to deconstruct arguments
+  | OmitAssortedPruning  -- ^ omit other assorted pruning rules
+  | OmitEarlyTests       -- ^ don't perform tests early-and-independently on each binding
+  | DontCopyBindings     -- ^ don't copy partial definition bindings in candidates
+  | AtomicNumbers        -- ^ restrict constant/ground numeric expressions to atoms
+  | NonAtomicNumbers     -- ^ lift constant/ground numetic expression restrictions
+  | UniqueCandidates     -- ^ unique-modulo-testing candidates
+  deriving (Eq, Ord, Show, Read)
+
+
+-- | Constructs an ingredient from a setting
+setting :: Setting -> Ingredient
+setting x  =  (val x, error "Conjure.Settings: evaluating reification, this is a bug")
+  -- using 'id' instead of 'error' above would work,
+  -- but we want to be warned in case we accidentally evaluate the reification
+
+extract :: Ingredient -> Setting
+extract  =  eval Noop . fst
+
+-- | Lists actual incredients in the list
+actual :: [Ingredient] -> [Ingredient]
+actual is  =  [i | i <- is, typ (fst i) /= typeOf Noop]
+
+-- | By default,
+-- 'Conjure.conjure' tests candidates up to a maximum of 360 tests.
+-- This configures the maximum number of tests to each candidate,
+-- when provided in the list of ingredients:
+--
+-- > conjure "..." ... [ ...
+-- >                   , maxTests 1080
+-- >                   , ... ]
+maxTests :: Int -> Ingredient
+maxTests =  setting . MaxTests
+
+-- | Finds the set maximum number of tests or set the default of 360
+maxTestsI  :: [Ingredient] -> Int
+maxTestsI is  =  headOr 360 [m | MaxTests m <- map extract is]
+  -- the use of magic numbers goes well with the theme of Conjure.
+
+-- | By default,
+-- 'Conjure.conjure' imposes no limit on the size of candidates.
+--
+-- This configures a different maximum
+-- when provided in the list of ingredients.
+--
+-- If only one of 'maxSize' and 'target' is defined,
+-- it is used.  If none, target is used.
+maxSize :: Int -> Ingredient
+maxSize =  setting . MaxSize
+
+-- | By default, 'Conjure.conjure' targets testing 10080 candidates.
+-- This configures a different target when
+-- provided in the list of ingredients:
+--
+-- > conjure "..." ... [ ...
+-- >                   , target 5040
+-- >                   , ... ]
+target :: Int -> Ingredient
+target =  setting . Target
+
+-- | Computes the target and maxSize.
+--
+-- When none is provided, we default to a target of 10080.
+targetAndMaxSizeI :: [Ingredient] -> (Int, Int)
+targetAndMaxSizeI is  =
+  case (t, m) of
+  (0, 0) -> (10080, 0)
+  (t, m) -> (t, m)
+  where
+  t  =  headOr 0 [m | Target m  <- map extract is]
+  m  =  headOr 0 [m | MaxSize m <- map extract is]
+-- above is a perfect use for the These datatype,
+-- one of my favourite non-standard,
+-- but I don't want to impose a dependency on my users...
+
+-- | By default,
+-- 'Conjure.conjure' evaluates candidates for up to 60 recursive calls.
+--
+-- This allows overriding the default
+-- when provided in the ingredient list.
+maxRecursions :: Int -> Ingredient
+maxRecursions =  setting . MaxRecursions
+
+maxRecursionsI :: [Ingredient] -> Int
+maxRecursionsI is  =  headOr 60 [m | MaxRecursions m <- map extract is]
+
+
+-- | By default,
+-- 'Conjure.conjure' considers equations of up to 5 symbols
+-- for pruning-through-rewriting.
+--
+-- This allows overriding the default:
+-- 6 or 7 are also good values for this depending on the number of ingredients.
+--
+-- > conjure ... ... [ ...
+-- >                 , maxEquationSize 6
+-- >                 , ... ]
+--
+-- Internally, this is the maximum size passed to the Speculate tool.
+maxEquationSize :: Int -> Ingredient
+maxEquationSize =  setting . MaxEquationSize
+
+maxEquationSizeI :: [Ingredient] -> Int
+maxEquationSizeI is  =  headOr 5 [m | MaxEquationSize m <- map extract is]
+
+
+-- | By default,
+-- 'Conjure.conjure' enumerates up to 110880 argument combinations
+-- while reifying the partial definition passed by the user.
+--
+-- This allows configuring a higher default
+-- when provided in the ingredient list.
+--
+-- Increasing this setting is useful
+-- when the partial definition is not exercised enough.
+maxSearchTests :: Int -> Ingredient
+maxSearchTests =  setting . MaxSearchTests
+
+maxSearchTestsI :: [Ingredient] -> Int
+maxSearchTestsI is  =  headOr 110880 [m | MaxSearchTests m <- map extract is]
+
+-- | By default
+-- 'Conjure.conjure' allows deconstruction expressions
+-- of up to 4 symbols.
+--
+-- This allows overriding the default
+-- when provided in the ingredient list.
+maxDeconstructionSize :: Int -> Ingredient
+maxDeconstructionSize =  setting . MaxDeconstructionSize
+
+maxDeconstructionSizeI :: [Ingredient] -> Int
+maxDeconstructionSizeI is  =  headOr 4 [m | MaxDeconstructionSize m <- map extract is]
+
+-- | Configures a maximum size of constant sub-expressions
+-- when provided in the ingredient list
+-- of 'Conjure.conjure' or 'Conjure.conjureFromSpec'.
+maxConstantSize :: Int -> Ingredient
+maxConstantSize =  setting . MaxConstantSize
+
+maxConstantSizeI :: [Ingredient] -> Int
+maxConstantSizeI is  =  headOr 0 [m | MaxConstantSize m <- map extract is]
+
+-- | By default,
+-- 'Conjure.conjure' places no limit in the LHS pattern sizes.
+--
+-- This allows configuring a limit when provided in the ingredient list
+maxPatternSize :: Int -> Ingredient
+maxPatternSize =  setting . MaxPatternSize
+
+maxPatternSizeI :: [Ingredient] -> Int
+maxPatternSizeI is  =  headOr 0 [m | MaxPatternSize m <- map extract is]
+
+-- | By default,
+-- 'Conjure.conjure' enumerates pattern breakdowns of the outernmost constructor
+-- of depth 1.
+--
+-- This allows overriding the default when provided in the ingredient list:
+-- a depth of 2 allows breakdowns of the two outernmost constructors;
+-- a depth of 3, three outernmost constructors;
+-- etc.
+maxPatternDepth :: Int -> Ingredient
+maxPatternDepth =  setting . MaxPatternDepth
+
+maxPatternDepthI :: [Ingredient] -> Int
+maxPatternDepthI is  =  headOr 1 [m | MaxPatternDepth m <- map extract is]
+
+-- | Carry on after finding a suitable candidate.
+--   To be provided as a setting in the list of ingredients.
+carryOn :: Ingredient
+carryOn =  setting CarryOn
+
+carryOnI :: [Ingredient] -> Bool
+carryOnI is  =  notNull [True | CarryOn <- map extract is]
+
+-- | (Debug option).
+--   Shows the underlying theory used in pruning
+--   when this is provided in the ingredient list.
+showTheory :: Ingredient
+showTheory =  setting ShowTheory
+
+showTheoryI :: [Ingredient] -> Bool
+showTheoryI is  =  notNull [True | ShowTheory <- map extract is]
+
+-- | (Debug option)
+--   When provided in the ingredient list,
+--   this reverts to a legacy enumeration that
+--   contains candidates with a single LHS matching everything.
+singlePattern :: Ingredient
+singlePattern =  setting SinglePattern
+
+singlePatternI :: [Ingredient] -> Bool
+singlePatternI is  =  notNull [True | SinglePattern <- map extract is]
+
+-- | (Debug option)
+-- When provided in the ingredients list,
+-- this enables showing enumerated candidates.
+--
+-- > conjure ... ... [ ...
+-- >                 , showCandidates
+-- >                 , ... ]
+--
+-- Warning: activating this will likely produce a humongous wall-of-text.
+showCandidates :: Ingredient
+showCandidates =  setting ShowCandidates
+
+showCandidatesI :: [Ingredient] -> Bool
+showCandidatesI is  =  notNull [True | ShowCandidates <- map extract is]
+
+-- | (Debug option)
+-- When provided in the ingredients list,
+-- 'Conjure.conjure' will print the tests reified from the partial definition.
+-- (cf. 'maxTests', 'maxSearchTests')
+showTests :: Ingredient
+showTests =  setting ShowTests
+
+showTestsI :: [Ingredient] -> Bool
+showTestsI is  =  notNull [True | ShowTests <- map extract is]
+
+-- | (Debug option)
+-- When this option is provided in the ingredients list,
+-- 'Conjure.conjure' will print the enumrated LHS patterns.
+-- (cf. 'maxPatternSize', 'maxPatternDepth')
+showPatterns :: Ingredient
+showPatterns =  setting ShowPatterns
+
+showPatternsI :: [Ingredient] -> Bool
+showPatternsI is  =  notNull [True | ShowPatterns <- map extract is]
+
+-- | (Debug option)
+-- Makes 'Conjure.conjure' print enumerated deconstructions
+-- when provided in its ingredient list.
+showDeconstructions :: Ingredient
+showDeconstructions =  setting ShowDeconstructions
+
+showDeconstructionsI :: [Ingredient] -> Bool
+showDeconstructionsI is  =  notNull [True | ShowDeconstructions <- map extract is]
+
+-- | Disables rewriting-as-pruning
+--   when provided in the ingredient list
+--   of 'Conjure.conjure' or 'Conjure.conjureFromSpec'.
+dontRewrite :: Ingredient
+dontRewrite  =  setting DontRewrite
+
+rewriteI :: [Ingredient] -> Bool
+rewriteI is  =  null [False | DontRewrite <- map extract is]
+
+-- | Disables the recursive descent requirement
+--   when provided in the ingredient list
+--   of 'Conjure.conjure' or 'Conjure.conjureFromSpec'.
+dontRequireDescent :: Ingredient
+dontRequireDescent  =  setting DontRequireDescent
+
+requireDescentI :: [Ingredient] -> Bool
+requireDescentI is  =  null [False | DontRequireDescent <- map extract is]
+
+-- | Disables assorted pruning rules
+--   when provided in the ingredient list
+--   of 'Conjure.conjure' or 'Conjure.conjureFromSpec'.
+omitAssortedPruning :: Ingredient
+omitAssortedPruning  =  setting OmitAssortedPruning
+
+assortedPruningI :: [Ingredient] -> Bool
+assortedPruningI is  =  null [False | OmitAssortedPruning <- map extract is]
+
+-- | Omits early tests
+--   when provided in the ingredient list
+--   of 'Conjure.conjure' or 'Conjure.conjureFromSpec'.
+omitEarlyTests :: Ingredient
+omitEarlyTests  =  setting OmitEarlyTests
+
+earlyTestsI :: [Ingredient] -> Bool
+earlyTestsI is  =  null [False | OmitEarlyTests <- map extract is]
+
+-- | Disables the copy-bindings rule
+--   when provided in the ingredient list
+--   of 'Conjure.conjure' or 'Conjure.conjureFromSpec'.
+dontCopyBindings :: Ingredient
+dontCopyBindings  =  setting DontCopyBindings
+
+copyBindingsI :: [Ingredient] -> Bool
+copyBindingsI is  =  null [False | DontCopyBindings <- map extract is]
+
+atomicNumbers :: Ingredient
+atomicNumbers =  setting AtomicNumbers
+
+-- | Disables the requirement of atomic numeric expressions
+--   when provided in the ingredient list
+--   of 'Conjure.conjure' or 'Conjure.conjureFromSpec'.
+--   (cf. 'maxConstantSize')
+nonAtomicNumbers :: Ingredient
+nonAtomicNumbers =  setting NonAtomicNumbers
+
+atomicNumbersI :: [Ingredient] -> Bool
+atomicNumbersI is  =  null [False | NonAtomicNumbers <- map extract is]
+
+-- | Enables expensive unique-modulo-testing candidates
+--   when provided in the ingredient list
+--   of 'Conjure.conjure' or 'Conjure.conjureFromSpec'.
+--
+-- Warning: this makes 'Conjure.conjure' very slow,
+-- it is only intended for approximating the theoretical
+-- limits of pruning in toy examples.
+uniqueCandidates :: Ingredient
+uniqueCandidates =  setting UniqueCandidates
+
+uniqueCandidatesI :: [Ingredient] -> Bool
+uniqueCandidatesI is  =  notNull [True | UniqueCandidates <- map extract is]
diff --git a/src/Conjure/Utils.hs b/src/Conjure/Utils.hs
--- a/src/Conjure/Utils.hs
+++ b/src/Conjure/Utils.hs
@@ -28,6 +28,7 @@
   , mapHead
   , sets
   , headOr
+  , notNull
   , allEqual
   , allEqualOn
   , allEqual2
@@ -150,6 +151,13 @@
 headOr :: a -> [a] -> a
 headOr x []  =  x
 headOr _ (x:xs)  =  x
+
+-- | Is the given list not null?
+--
+-- Equivalent to @not . null@
+notNull :: [a] -> Bool
+notNull []  =  False
+notNull (_:_)  =  True
 
 -- | Lists choices of values.
 choices :: [a] -> [(a,[a])]
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -55,14 +55,17 @@
 -- were correctly generated.
 conjurableOK :: (Eq a, Show a, Express a, Listable a, Conjurable a) => a -> Bool
 conjurableOK x  =  and
-  [ holds 60 $ (-==-) ==== (==)
+  [ null (conjureArgumentHoles x) -- conjurableOK is for non-functional types
+  , holds 60 $ (-==-) ==== (==)
   , holds 60 $ expr' === expr
   , tiers' =| 6 |= (mapT val $ tiers -: [[x]])
   , all isWellTyped cases'
   , all (\c -> typ c == typeOf x) cases'
+  , isWellTyped (if' :$ (val True) :$ (value "undefined" x) :$ (value "undefined" x))
   ]
   where
   (-==-)  =  evl (fromJust $ conjureEquality x) -:> x
   expr'  =  (conjureExpress x . val) -:> x
   cases'  =  conjureCases x
   tiers'  =  conjureTiersFor x (hole x)
+  if'  =  conjureIf x
diff --git a/test/factorial.hs b/test/factorial.hs
new file mode 100644
--- /dev/null
+++ b/test/factorial.hs
@@ -0,0 +1,24 @@
+-- factorial.hs: conjuring a factorial function
+--
+-- Copyright (C) 2021-2025 Rudy Matela
+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).
+import Conjure
+
+factorial :: Int -> Int
+factorial 1  =  1
+factorial 2  =  2
+factorial 3  =  6
+factorial 4  =  24
+
+main :: IO ()
+main  =  do
+  conjure "factorial n" factorial
+    [ con (0::Int)
+    , con (1::Int)
+    , fun "+" ((+) :: Int -> Int -> Int)
+    , fun "*" ((*) :: Int -> Int -> Int)
+    , fun "-" ((-) :: Int -> Int -> Int)
+    ]
+  -- should produce:
+  -- factorial 0  =  1
+  -- factorial x  =  x * factorial (x - 1)
