diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -64,9 +64,6 @@
 test-via-stack:
 	stack test code-conjure:test:expr --ghc-options="$(GHCFLAGS) -O0" --system-ghc --no-install-ghc --no-terminal
 
-hugs-test:
-	echo 'Unsupported'
-
 clean: clean-hi-o clean-haddock
 	rm -f $(EG) $(TESTS) mk/toplibs
 
diff --git a/TODO.md b/TODO.md
--- a/TODO.md
+++ b/TODO.md
@@ -3,11 +3,6 @@
 
 A non-exhaustive list of things TO DO for Conjure.
 
-* think about how can we allow gcd to be produced
-
-* use holes for recursions, code will probably become cleaner
-  (and possibly faster)
-
 * generate functions with top-level case patterns:
 
         len []  =  0
@@ -15,6 +10,10 @@
 
 
 ### for later
+
+* add machinery to reify `Int -> Int` from the `(Expr,Expr)` definition
+
+* allow specifying properties that need to be true
 
 * allow recursion under any lazy functions (discover them by testing!)
 
diff --git a/bench/ill-hit.out b/bench/ill-hit.out
--- a/bench/ill-hit.out
+++ b/bench/ill-hit.out
@@ -8,8 +8,8 @@
 -- looking through 5 candidates of size 6
 -- looking through 15 candidates of size 7
 -- looking through 27 candidates of size 8
--- looking through 53 candidates of size 9
--- looking through 101 candidates of size 10
+-- looking through 57 candidates of size 9
+-- looking through 119 candidates of size 10
 sum xs  =  if null xs then 0 else head xs + sum (tail xs)
 
 sum :: [Int] -> Int
@@ -22,8 +22,8 @@
 -- looking through 5 candidates of size 6
 -- looking through 15 candidates of size 7
 -- looking through 27 candidates of size 8
--- looking through 53 candidates of size 9
--- looking through 101 candidates of size 10
+-- looking through 57 candidates of size 9
+-- looking through 119 candidates of size 10
 sum xs  =  if null xs then 0 else head xs + sum (tail xs)
 
 sum :: [Int] -> Int
@@ -36,7 +36,7 @@
 -- looking through 5 candidates of size 6
 -- looking through 15 candidates of size 7
 -- looking through 27 candidates of size 8
--- looking through 53 candidates of size 9
--- looking through 101 candidates of size 10
+-- looking through 57 candidates of size 9
+-- looking through 119 candidates of size 10
 sum xs  =  if null xs then 0 else head xs + sum (tail xs)
 
diff --git a/bench/longshot.out b/bench/longshot.out
--- a/bench/longshot.out
+++ b/bench/longshot.out
@@ -10,8 +10,8 @@
 -- looking through 611 candidates of size 8
 -- looking through 1779 candidates of size 9
 -- looking through 5301 candidates of size 10
--- looking through 16103 candidates of size 11
--- looking through 49113 candidates of size 12
+-- looking through 16107 candidates of size 11
+-- looking through 49149 candidates of size 12
 cannot conjure
 
 pow :: Int -> Int -> Int
@@ -51,7 +51,7 @@
 -- looking through 154 candidates of size 9
 -- looking through 366 candidates of size 10
 -- looking through 914 candidates of size 11
--- looking through 2234 candidates of size 12
+-- looking through 2238 candidates of size 12
 cannot conjure
 
 positionsFrom :: Int -> Int -> [Int] -> [Int]
@@ -66,7 +66,7 @@
 -- looking through 170 candidates of size 8
 -- looking through 358 candidates of size 9
 -- looking through 810 candidates of size 10
--- looking through 2046 candidates of size 11
--- looking through 5578 candidates of size 12
+-- looking through 2070 candidates of size 11
+-- looking through 5706 candidates of size 12
 cannot conjure
 
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.1
+1.2
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 @@
-4.3
+4.7
diff --git a/bench/runtime/zero/bench/take-drop.runtime b/bench/runtime/zero/bench/take-drop.runtime
--- a/bench/runtime/zero/bench/take-drop.runtime
+++ b/bench/runtime/zero/bench/take-drop.runtime
@@ -1,1 +1,1 @@
-5.8
+7.2
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 @@
-0.8
+0.9
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 @@
-2.8
+3.0
diff --git a/bench/runtime/zero/eg/count.runtime b/bench/runtime/zero/eg/count.runtime
--- a/bench/runtime/zero/eg/count.runtime
+++ b/bench/runtime/zero/eg/count.runtime
@@ -1,1 +1,1 @@
-2.3
+3.2
diff --git a/bench/runtime/zero/eg/factorial.runtime b/bench/runtime/zero/eg/factorial.runtime
--- a/bench/runtime/zero/eg/factorial.runtime
+++ b/bench/runtime/zero/eg/factorial.runtime
@@ -1,1 +1,1 @@
-1.4
+1.5
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 @@
-20.8
+22.2
diff --git a/bench/runtime/zero/eg/gcd.runtime b/bench/runtime/zero/eg/gcd.runtime
--- a/bench/runtime/zero/eg/gcd.runtime
+++ b/bench/runtime/zero/eg/gcd.runtime
@@ -1,1 +1,1 @@
-0.3
+0.1
diff --git a/bench/runtime/zero/eg/list.runtime b/bench/runtime/zero/eg/list.runtime
--- a/bench/runtime/zero/eg/list.runtime
+++ b/bench/runtime/zero/eg/list.runtime
@@ -1,1 +1,1 @@
-0.4
+0.5
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 @@
-23.3
+22.5
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 @@
-4.6
+5.6
diff --git a/bench/take-drop.out b/bench/take-drop.out
--- a/bench/take-drop.out
+++ b/bench/take-drop.out
@@ -8,11 +8,11 @@
 -- looking through 1 candidates of size 6
 -- looking through 1 candidates of size 7
 -- looking through 7 candidates of size 8
--- looking through 33 candidates of size 9
--- looking through 100 candidates of size 10
--- looking through 236 candidates of size 11
--- looking through 510 candidates of size 12
--- looking through 1069 candidates of size 13
+-- looking through 35 candidates of size 9
+-- looking through 109 candidates of size 10
+-- looking through 261 candidates of size 11
+-- looking through 567 candidates of size 12
+-- looking through 1183 candidates of size 13
 drop x xs  =  if null xs || x == 0 then xs else drop (dec x) (tail xs)
 
 take :: Int -> [A] -> [A]
@@ -25,13 +25,13 @@
 -- looking through 14 candidates of size 6
 -- looking through 26 candidates of size 7
 -- looking through 62 candidates of size 8
--- looking through 176 candidates of size 9
--- looking through 470 candidates of size 10
--- looking through 1190 candidates of size 11
--- looking through 3116 candidates of size 12
--- looking through 8020 candidates of size 13
--- looking through 19658 candidates of size 14
--- looking through 46906 candidates of size 15
--- looking through 109976 candidates of size 16
+-- looking through 182 candidates of size 9
+-- looking through 498 candidates of size 10
+-- looking through 1270 candidates of size 11
+-- looking through 3346 candidates of size 12
+-- looking through 8650 candidates of size 13
+-- looking through 21270 candidates of size 14
+-- looking through 51166 candidates of size 15
+-- looking through 121430 candidates of size 16
 take x xs  =  if null xs || x == 0 then [] else head xs:take (dec x) (tail xs)
 
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -2,6 +2,17 @@
 ============================
 
 
+v0.3.6
+------
+
+* add switch for descending recursions
+  to allow generation of `gcd`
+* refactor recursion generation (replace a hole later)
+* change `conjpureWith` to take `Args`
+* rename two args fields to `maxBodyRecursions` and `maxEvalRecursions`
+  at this point, the old names were misnomers.
+
+
 v0.3.4
 ------
 
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 Rudy Matela
 -- Distributed under the 3-Clause BSD licence (see the file LICENSE).
 name:                code-conjure
-version:             0.3.4
+version:             0.3.6
 synopsis:            conjure Haskell functions out of partial definitions
 description:
   Conjure is a tool that produces Haskell functions out of partial definitions.
@@ -65,7 +65,7 @@
 source-repository this
   type:            git
   location:        https://github.com/rudymatela/conjure
-  tag:             v0.3.4
+  tag:             v0.3.6
 
 library
   exposed-modules: Conjure
diff --git a/eg/bools.out b/eg/bools.out
--- a/eg/bools.out
+++ b/eg/bools.out
@@ -8,7 +8,7 @@
 -- looking through 19 candidates of size 6
 -- looking through 45 candidates of size 7
 -- looking through 80 candidates of size 8
--- looking through 156 candidates of size 9
+-- looking through 172 candidates of size 9
 and ps  =  null ps || head ps && and (tail ps)
 
 or :: [Bool] -> Bool
@@ -21,8 +21,8 @@
 -- looking through 19 candidates of size 6
 -- looking through 45 candidates of size 7
 -- looking through 80 candidates of size 8
--- looking through 156 candidates of size 9
--- looking through 382 candidates of size 10
+-- looking through 172 candidates of size 9
+-- looking through 454 candidates of size 10
 or ps  =  not (null ps) && (head ps || or (tail ps))
 
 and :: [Bool] -> Bool
diff --git a/eg/count.out b/eg/count.out
--- a/eg/count.out
+++ b/eg/count.out
@@ -9,12 +9,12 @@
 -- looking through 13 candidates of size 7
 -- looking through 16 candidates of size 8
 -- looking through 57 candidates of size 9
--- looking through 84 candidates of size 10
--- looking through 242 candidates of size 11
--- looking through 401 candidates of size 12
--- looking through 1045 candidates of size 13
--- looking through 1895 candidates of size 14
--- looking through 4672 candidates of size 15
--- looking through 8990 candidates of size 16
-count x xs  =  if null xs then 0 else count x (tail xs) + (if x == head xs then 1 else 0)
+-- looking through 90 candidates of size 10
+-- looking through 258 candidates of size 11
+-- looking through 448 candidates of size 12
+-- looking through 1145 candidates of size 13
+-- looking through 2144 candidates of size 14
+-- looking through 5212 candidates of size 15
+-- looking through 10296 candidates of size 16
+count x xs  =  if null xs then 0 else (if head xs == x then 1 else 0) + count x (tail xs)
 
diff --git a/eg/factorial.out b/eg/factorial.out
--- a/eg/factorial.out
+++ b/eg/factorial.out
@@ -15,8 +15,8 @@
 -- looking through 20 candidates of size 5
 -- looking through 27 candidates of size 6
 -- looking through 87 candidates of size 7
--- looking through 167 candidates of size 8
--- looking through 417 candidates of size 9
--- looking through 960 candidates of size 10
+-- looking through 173 candidates of size 8
+-- looking through 434 candidates of size 9
+-- looking through 1016 candidates of size 10
 factorial n  =  if n == 0 then 1 else n * factorial (dec n)
 
diff --git a/eg/fibonacci.hs b/eg/fibonacci.hs
--- a/eg/fibonacci.hs
+++ b/eg/fibonacci.hs
@@ -22,7 +22,7 @@
 fib01 0 1 7  =  21
 
 as :: Args
-as  =  args{maxSize=13,maxRecursiveCalls=2}
+as  =  args{maxSize=13,maxBodyRecursions=2}
 
 main :: IO ()
 main  =  do
diff --git a/eg/fibonacci.out b/eg/fibonacci.out
--- a/eg/fibonacci.out
+++ b/eg/fibonacci.out
@@ -9,10 +9,10 @@
 -- looking through 27 candidates of size 7
 -- looking through 20 candidates of size 8
 -- looking through 95 candidates of size 9
--- looking through 140 candidates of size 10
--- looking through 407 candidates of size 11
--- looking through 825 candidates of size 12
--- looking through 2153 candidates of size 13
+-- looking through 172 candidates of size 10
+-- looking through 519 candidates of size 11
+-- looking through 1281 candidates of size 12
+-- looking through 3281 candidates of size 13
 fibonacci n  =  if n <= 1 then 1 else fibonacci (dec n) + fibonacci (dec (dec n))
 
 fib01 :: Int -> Int -> Int -> Int
@@ -27,7 +27,7 @@
 -- looking through 391 candidates of size 8
 -- looking through 840 candidates of size 9
 -- looking through 9294 candidates of size 10
--- looking through 37807 candidates of size 11
--- looking through 166308 candidates of size 12
+-- looking through 45295 candidates of size 11
+-- looking through 215844 candidates of size 12
 fib01 x y z  =  if z <= 0 then y else fib01 y (x + y) (dec z)
 
diff --git a/eg/gcd.hs b/eg/gcd.hs
--- a/eg/gcd.hs
+++ b/eg/gcd.hs
@@ -18,7 +18,7 @@
 gcd' 12 18  =  6
 
 main :: IO ()
-main = conjure "gcd a b" gcd'
+main = conjureWith args{requireDescent=False} "gcd a b" gcd'
   [ val (0::Int)
   , value "`mod`" (mod :: Int -> Int -> Int)
   , value "==" ((==) :: Int -> Int -> Bool)
@@ -26,4 +26,3 @@
   -- desired function:
   -- gcd a b  =  if b == 0 then a else gcd b (a `mod` b)
   --             1  2 3  4      5      6   7  8  9   10
-  -- TODO: make it so that conjure is able to find this
diff --git a/eg/gcd.out b/eg/gcd.out
--- a/eg/gcd.out
+++ b/eg/gcd.out
@@ -7,10 +7,8 @@
 -- looking through 54 candidates of size 5
 -- looking through 0 candidates of size 6
 -- looking through 405 candidates of size 7
--- looking through 0 candidates of size 8
+-- looking through 90 candidates of size 8
 -- looking through 3402 candidates of size 9
--- looking through 0 candidates of size 10
--- looking through 30618 candidates of size 11
--- looking through 0 candidates of size 12
-cannot conjure
+-- looking through 2016 candidates of size 10
+gcd a b  =  if a == 0 then b else gcd (b `mod` a) a
 
diff --git a/eg/ints.out b/eg/ints.out
--- a/eg/ints.out
+++ b/eg/ints.out
@@ -23,8 +23,8 @@
 -- looking through 5 candidates of size 6
 -- looking through 15 candidates of size 7
 -- looking through 27 candidates of size 8
--- looking through 53 candidates of size 9
--- looking through 101 candidates of size 10
+-- looking through 57 candidates of size 9
+-- looking through 119 candidates of size 10
 sum xs  =  if null xs then 0 else head xs + sum (tail xs)
 
 product :: [Int] -> Int
@@ -37,8 +37,8 @@
 -- looking through 5 candidates of size 6
 -- looking through 15 candidates of size 7
 -- looking through 27 candidates of size 8
--- looking through 53 candidates of size 9
--- looking through 101 candidates of size 10
+-- looking through 57 candidates of size 9
+-- looking through 119 candidates of size 10
 product xs  =  if null xs then 1 else head xs * product (tail xs)
 
 sum :: [Int] -> Int
diff --git a/eg/list.out b/eg/list.out
--- a/eg/list.out
+++ b/eg/list.out
@@ -8,7 +8,7 @@
 -- looking through 0 candidates of size 6
 -- looking through 5 candidates of size 7
 -- looking through 8 candidates of size 8
--- looking through 19 candidates of size 9
+-- looking through 23 candidates of size 9
 length xs  =  if null xs then 0 else 1 + length (tail xs)
 
 reverse :: [Int] -> [Int]
@@ -23,7 +23,7 @@
 -- looking through 381 candidates of size 8
 -- looking through 1014 candidates of size 9
 -- looking through 2736 candidates of size 10
--- looking through 7447 candidates of size 11
+-- looking through 7451 candidates of size 11
 reverse xs  =  if null xs then xs else reverse (tail xs) ++ unit (head xs)
 
 sort :: [Int] -> [Int]
diff --git a/eg/setelem.hs b/eg/setelem.hs
--- a/eg/setelem.hs
+++ b/eg/setelem.hs
@@ -7,20 +7,22 @@
 elem' x [y,z,w]  =  x == y || x == z || x == w
 
 set' :: [Int] -> Bool
+set' []  =  True
 set' [x]  =  True
 set' [x,y]  =  not (x == y)
 set' [x,y,z]  =  not (x == y || y == z || x == z)
 
 main :: IO ()
 main = do
-  -- elem x xs  =  if null xs then False else elem x (tail xs) || x == head xs
+  -- elem x xs  =  not (null xs) && (elem x (tail xs) || x == head xs)
+  --               1    2    3    4  5    6   7   8   9  10 11 12  13
   conjureWithMaxSize 13 "elem" (elem')
     [ val ([] :: [Int])
     , val True
     , val False
-    , value "not" not
     , value "||" (||)
     , value "&&" (&&)
+    , value "not" not
     , value ":" ((:) :: Int -> [Int] -> [Int])
     , value "head" (head :: [Int] -> Int)
     , value "tail" (tail :: [Int] -> [Int])
@@ -28,14 +30,15 @@
     , value "==" ((==) :: Int -> Int -> Bool)
     ]
 
-  -- set xs  =  if null xs then True else not (head xs `elem` tail xs) && set (tail xs)
-  conjureWithMaxSize 14 "set" (set')
+  -- set xs  =  null xs || set (tail xs) && not (elem (head xs) (tail xs))
+  --            1    2  3  4    5    6    7  8    9    10   11   12   13
+  conjureWithMaxSize 13 "set" (set')
     [ val ([] :: [Int])
     , val True
     , val False
-    , value "not" not
-    , value "||" (||)
     , value "&&" (&&)
+    , value "||" (||)
+    , value "not" not
     , value ":" ((:) :: Int -> [Int] -> [Int])
     , value "head" (head :: [Int] -> Int)
     , value "tail" (tail :: [Int] -> [Int])
diff --git a/eg/setelem.out b/eg/setelem.out
--- a/eg/setelem.out
+++ b/eg/setelem.out
@@ -6,14 +6,14 @@
 -- looking through 8 candidates of size 4
 -- looking through 14 candidates of size 5
 -- looking through 25 candidates of size 6
--- looking through 57 candidates of size 7
--- looking through 137 candidates of size 8
--- looking through 320 candidates of size 9
--- looking through 720 candidates of size 10
--- looking through 1737 candidates of size 11
--- looking through 4204 candidates of size 12
--- looking through 10333 candidates of size 13
-elem x xs  =  not (null xs) && (elem x (tail xs) || x == head xs)
+-- looking through 60 candidates of size 7
+-- looking through 145 candidates of size 8
+-- looking through 332 candidates of size 9
+-- looking through 747 candidates of size 10
+-- looking through 1826 candidates of size 11
+-- looking through 4407 candidates of size 12
+-- looking through 10888 candidates of size 13
+elem x xs  =  not (null xs) && (head xs == x || elem x (tail xs))
 
 set :: [Int] -> Bool
 -- testing 60 combinations of argument values
@@ -23,13 +23,12 @@
 -- looking through 5 candidates of size 4
 -- looking through 11 candidates of size 5
 -- looking through 26 candidates of size 6
--- looking through 61 candidates of size 7
--- looking through 142 candidates of size 8
--- looking through 302 candidates of size 9
--- looking through 692 candidates of size 10
--- looking through 1651 candidates of size 11
--- looking through 3945 candidates of size 12
--- looking through 9309 candidates of size 13
--- looking through 22246 candidates of size 14
-set xs  =  not (elem (head xs) (tail xs)) && (null (tail xs) || set (tail xs))
+-- looking through 64 candidates of size 7
+-- looking through 145 candidates of size 8
+-- looking through 310 candidates of size 9
+-- looking through 717 candidates of size 10
+-- looking through 1734 candidates of size 11
+-- looking through 4135 candidates of size 12
+-- looking through 9734 candidates of size 13
+set xs  =  null xs || not (elem (head xs) (tail xs)) && set (tail xs)
 
diff --git a/eg/spec.out b/eg/spec.out
--- a/eg/spec.out
+++ b/eg/spec.out
@@ -9,7 +9,7 @@
 -- looking through 5 candidates of size 7
 -- looking through 10 candidates of size 8
 -- looking through 17 candidates of size 9
--- looking through 28 candidates of size 10
+-- looking through 30 candidates of size 10
 sum xs  =  if null xs then 0 else head xs + sum (tail xs)
 
 (++) :: [Int] -> [Int] -> [Int]
diff --git a/eg/tapps.out b/eg/tapps.out
--- a/eg/tapps.out
+++ b/eg/tapps.out
@@ -16,8 +16,8 @@
 -- looking through 5 candidates of size 6
 -- looking through 15 candidates of size 7
 -- looking through 27 candidates of size 8
--- looking through 53 candidates of size 9
--- looking through 101 candidates of size 10
+-- looking through 57 candidates of size 9
+-- looking through 119 candidates of size 10
 product xs  =  if null xs then 1 else head xs * product (tail xs)
 
 product :: [Int] -> Int
diff --git a/eg/tree.hs b/eg/tree.hs
--- a/eg/tree.hs
+++ b/eg/tree.hs
@@ -91,7 +91,7 @@
     , value "right" right
     ]
 
-  conjureWith args{maxRecursiveCalls=2, maxSize=13} "size" size
+  conjureWith args{maxBodyRecursions=2, maxSize=13} "size" size
     [ val (0 :: Int)
     , val (1 :: Int)
     , value "+" ((+) :: Int -> Int -> Int)
@@ -100,7 +100,7 @@
     , value "right" right
     ]
 
-  conjureWith args{maxRecursiveCalls=2, maxSize=13} "height" height
+  conjureWith args{maxBodyRecursions=2, maxSize=13} "height" height
     [ val (0 :: Int)
     , val (1 :: Int)
     , val (-1 :: Int)
@@ -112,7 +112,7 @@
     ]
 
   -- out of reach performance-wise
-  conjureWith args{maxRecursiveCalls=2, maxSize=12} "mem" mem
+  conjureWith args{maxBodyRecursions=2, maxSize=12} "mem" mem
     [ val False
     , value "||" (||)
     , value "==" ((==) :: Int -> Int -> Bool)
@@ -123,7 +123,7 @@
     ]
 
   -- simply out of reach performance-wise (size 34)
-  conjureWith args{maxRecursiveCalls=2, maxSize=9} "insert" mem
+  conjureWith args{maxBodyRecursions=2, maxSize=9} "insert" mem
     [ val Leaf
     , value "Node" Node
     , value "left" left
diff --git a/eg/tree.out b/eg/tree.out
--- a/eg/tree.out
+++ b/eg/tree.out
@@ -34,11 +34,11 @@
 -- looking through 0 candidates of size 6
 -- looking through 9 candidates of size 7
 -- looking through 32 candidates of size 8
--- looking through 109 candidates of size 9
--- looking through 304 candidates of size 10
--- looking through 817 candidates of size 11
--- looking through 2080 candidates of size 12
--- looking through 5165 candidates of size 13
+-- looking through 117 candidates of size 9
+-- looking through 336 candidates of size 10
+-- looking through 933 candidates of size 11
+-- looking through 2416 candidates of size 12
+-- looking through 6113 candidates of size 13
 size x  =  if nil x then 0 else 1 + (size (left x) + size (right x))
 
 height :: Tree -> Int
@@ -51,12 +51,12 @@
 -- looking through 0 candidates of size 6
 -- looking through 21 candidates of size 7
 -- looking through 48 candidates of size 8
--- looking through 239 candidates of size 9
--- looking through 656 candidates of size 10
--- looking through 2149 candidates of size 11
--- looking through 5704 candidates of size 12
--- looking through 16380 candidates of size 13
-height x  =  if nil x then -1 else 1 + max (height (left x)) (height (right x))
+-- looking through 299 candidates of size 9
+-- looking through 896 candidates of size 10
+-- looking through 3113 candidates of size 11
+-- looking through 8528 candidates of size 12
+-- looking through 24896 candidates of size 13
+cannot conjure
 
 mem :: Int -> Tree -> Bool
 -- testing 60 combinations of argument values
@@ -69,9 +69,9 @@
 -- looking through 64 candidates of size 7
 -- looking through 156 candidates of size 8
 -- looking through 376 candidates of size 9
--- looking through 926 candidates of size 10
--- looking through 2280 candidates of size 11
--- looking through 5648 candidates of size 12
+-- looking through 930 candidates of size 10
+-- looking through 2302 candidates of size 11
+-- looking through 5752 candidates of size 12
 cannot conjure
 
 insert :: Int -> Tree -> Bool
diff --git a/src/Conjure/Engine.hs b/src/Conjure/Engine.hs
--- a/src/Conjure/Engine.hs
+++ b/src/Conjure/Engine.hs
@@ -94,10 +94,11 @@
 data Args = Args
   { maxTests          :: Int  -- ^ maximum number of tests to each candidate
   , maxSize           :: Int  -- ^ maximum size of candidate bodies
-  , maxRecursiveCalls :: Int  -- ^ maximum number of allowed recursive calls
+  , maxBodyRecursions :: Int  -- ^ maximum number of recursive calls in candidate bodies
+  , maxEvalRecursions :: Int  -- ^ maximum number of recursive evaluations when testing candidates
   , maxEquationSize   :: Int  -- ^ maximum size of equation operands
-  , maxRecursionSize  :: Int  -- ^ maximum size of a recursive expression expansion
   , maxSearchTests    :: Int  -- ^ maximum number of tests to search for defined values
+  , requireDescent    :: Bool -- ^ require recursive calls to deconstruct arguments
   , forceTests :: [[Expr]]  -- ^ force tests
   }
 
@@ -106,18 +107,20 @@
 --
 -- * 60 tests
 -- * functions of up to 12 symbols
--- * maximum of 1 recursive call
+-- * maximum of one recursive call allowed in candidate bodies
+-- * maximum evaluation of up to 60 recursions
 -- * pruning with equations up to size 5
--- * recursion up to 60 symbols
 -- * search for defined applications for up to 100000 combinations
+-- * require recursive calls to deconstruct arguments
 args :: Args
 args = Args
   { maxTests           =  60
   , maxSize            =  12
-  , maxRecursiveCalls  =   1
+  , maxBodyRecursions  =   1
+  , maxEvalRecursions  =  60
   , maxEquationSize    =   5
-  , maxRecursionSize   =  60
   , maxSearchTests     =  100000
+  , requireDescent     =  True
   , forceTests         =  []
   }
 
@@ -136,7 +139,7 @@
     putStrLn $ "-- looking through "
             ++ show (length cs)
             ++ " candidates of size " ++ show n
-    -- when (n<=7) $ putStrLn $ unlines $ map show es
+    -- when (n<=12) $ putStrLn $ unlines $ map show cs
     case is of
       []     ->  pr (n+1) rs
       (i:_)  ->  do putStrLn $ showEq i
@@ -159,23 +162,22 @@
 
 -- | Like 'conjpure' but allows setting options through 'Args' and 'args'.
 conjpureWith :: Conjurable f => Args -> String -> f -> [Expr] -> ([[Expr]], [[Expr]], [Expr])
-conjpureWith Args{..} nm f es  =  (implementationsT, candidatesT, tests)
+conjpureWith args@(Args{..}) nm f es  =  (implementationsT, candidatesT, tests)
   where
   tests  =  [ffxx //- bs | bs <- dbss]
   implementationsT  =  mapT (vffxx -==-) $ filterT implements candidatesT
   implements e  =  apparentlyTerminates rrff e
                 && requal (vffxx,e) ffxx vffxx
   candidatesT  =  take maxSize
-               $  candidateExprs nm f maxEquationSize maxRecursiveCalls (===) es
+               $  candidateExprs args nm f es
   ffxx   =  conjureApplication nm f
   vffxx  =  conjureVarApplication nm f
   (rrff:xxs)  =  unfoldApp vffxx
 
-  (===)  =  conjureAreEqual f maxTests
   requal dfn e1 e2  =  isTrueWhenDefined dfn (e1 -==- e2)
   (-==-)  =  conjureMkEquation f
 
-  isTrueWhenDefined dfn e  =  all (errorToFalse . reval dfn maxRecursionSize False) $ map (e //-) dbss
+  isTrueWhenDefined dfn e  =  all (errorToFalse . reval dfn maxEvalRecursions False) $ map (e //-) dbss
 
   bss, dbss :: [[(Expr,Expr)]]
   bss  =  take maxSearchTests $ groundBinds (conjureTiersFor f) ffxx
@@ -187,14 +189,8 @@
     e  =  ffxx -==- ffxx
 
 
-candidateExprs :: Conjurable f
-               => String -> f
-               -> Int
-               -> Int
-               -> (Expr -> Expr -> Bool)
-               -> [Expr]
-               -> [[Expr]]
-candidateExprs nm f sz mc (===) es  =  as \/ ts
+candidateExprs :: Conjurable f => Args -> String -> f -> [Expr] -> [[Expr]]
+candidateExprs Args{..} nm f es  =  as \/ concatMapT (`enumerateFillings` recs) ts
   where
   ts | typ efxs == boolTy  =  foldAppProducts andE [cs, rs]
                            \/ foldAppProducts orE  [cs, rs]
@@ -206,17 +202,21 @@
   as  =  forN efxs
   rs  =  forR efxs
   forN h  =  enumerateAppsFor h keep [exs ++ es]
-  forR h  =  filterT (\e -> (ef `elem`) (vars e))
-          $  enumerateAppsFor h keep $ [exs ++ es] \/ recs
+  forR h  =  filterT (\e -> (eh `elem`) (holes e))
+          $  enumerateAppsFor h keep $ [exs ++ es ++ [eh]]
+  eh  =  holeAsTypeOf efxs
   efxs  =  conjureVarApplication nm f
   (ef:exs)  =  unfoldApp efxs
   keep e  =  isRootNormalE thy e
-          && count (== ef) (vars e) <= mc
-  thy  =  theoryFromAtoms (===) sz . (:[]) . nub
-       $  conjureHoles f ++ [val False, val True] ++ es
-  ds  =  map snd $ deconstructors f 60 es
-  recs  =  filterT (descends (`elem` ds) efxs)
+          && count (== ef) (vars e) <= maxBodyRecursions
+  ds  =  map snd $ deconstructors f maxTests es
+  keepR | requireDescent  =  descends (`elem` ds) efxs
+        | otherwise       =  const True
+  recs  =  filterT keepR
         $  foldAppProducts ef [forN h | h <- conjureArgumentHoles f]
+  thy  =  theoryFromAtoms (===) maxEquationSize . (:[]) . nub
+       $  conjureHoles f ++ [val False, val True] ++ es
+  (===)  =  conjureAreEqual f maxTests
 
 -- | Returns whether the given recursive call
 --   deconstructs one of its arguments.
diff --git a/src/Conjure/Expr.hs b/src/Conjure/Expr.hs
--- a/src/Conjure/Expr.hs
+++ b/src/Conjure/Expr.hs
@@ -36,6 +36,7 @@
 
   , enumerateApps
   , enumerateAppsFor
+  , enumerateFillings
 
   , module Conjure.Utils
   )
@@ -50,7 +51,8 @@
 import Data.Dynamic
 import Control.Applicative ((<$>)) -- for GHC <= 7.8
 
-import Test.LeanCheck (filterT, (\/), delay, productWith, productMaybeWith)
+import Test.LeanCheck (mapT, filterT, (\/), delay, productWith, productMaybeWith)
+import Test.LeanCheck.Tiers (products)
 
 -- | /O(n)/.
 -- Compares the simplicity of two 'Expr's.
@@ -326,13 +328,18 @@
   for h  =  filterT (\e -> typ h == typ e) ess \/ delay apps
     where
     apps  =  foldr (\/) []
-          [  filterT keep $ productWith (:$) (for hf) (for hx)
+          [  filterT keep $ fliproductWith (:$) (for hf) (for hx)
           |  hf <- hs
           ,  hx <- hs
           ,  Just hfx <- [hf $$ hx]
           ,  typ h == typ hfx
           ]
 
+enumerateFillings :: Expr -> [[Expr]] -> [[Expr]]
+enumerateFillings e  =  mapT (fill e)
+                     .  products
+                     .  replicate (length $ holes e)
+
 -- Like 'isDeconstruction' but lifted over the 'Expr' type.
 isDeconstructionE :: [Expr] -> Expr -> Expr -> Bool
 --                   [a] -> (a -> Bool) -> (a -> a) -> Bool
@@ -383,3 +390,12 @@
 
 reval :: Typeable a => (Expr,Expr) -> Int -> a -> Expr -> a
 reval dfn n x e = fromMaybe x (revaluate dfn n e)
+
+-- | like 'productWith' but prefers enumerating from the second tiers first
+fliproductWith :: (a->b->c) -> [[a]] -> [[b]] -> [[c]]
+fliproductWith _ [] _  =  []
+fliproductWith _ _ []  =  []
+fliproductWith f xss (ys:yss)  =  map (** ys) xss
+                               \/ delay (productWith f xss yss)
+  where
+  xs ** ys  =  [x `f` y | x <- xs, y <- ys]
