diff --git a/examples/btree.hs b/examples/btree.hs
--- a/examples/btree.hs
+++ b/examples/btree.hs
@@ -21,4 +21,4 @@
 btreeShapes = take 5 unfold_
 
 randomBTree :: IO (TB Bool)
-randomBTree = getStdRandom randomValue
+randomBTree = getStdRandom randomDefault
diff --git a/examples/tree.hs b/examples/tree.hs
--- a/examples/tree.hs
+++ b/examples/tree.hs
@@ -22,4 +22,4 @@
 treeShapes = take 10 unfoldBF_
 
 randomTree :: IO (Tree Bool)
-randomTree = getStdRandom randomValue
+randomTree = getStdRandom randomDefault
diff --git a/src/Data/Unfoldable.hs b/src/Data/Unfoldable.hs
--- a/src/Data/Unfoldable.hs
+++ b/src/Data/Unfoldable.hs
@@ -26,7 +26,8 @@
   , rightMost
   , allDepthFirst
   , allBreadthFirst
-  , randomValue
+  , randomDefault
+  , arbitraryDefault
   
   ) 
   where
@@ -40,6 +41,8 @@
 import Data.Functor.Reverse
 import Control.Monad.Trans.State
 import qualified System.Random as R
+import Test.QuickCheck.Arbitrary (Arbitrary(..))
+import Test.QuickCheck.Gen (Gen(..))
 import Data.Maybe
 
 -- | Data structures that can be unfolded.
@@ -94,12 +97,12 @@
     uncons (a:as) = Just (a, as)
 
 -- | Always choose the first constructor.
-leftMost :: Unfoldable t => t ()
-leftMost = runIdentity $ getL unfold_
+leftMost :: Unfoldable t => Maybe (t ())
+leftMost = unfold_
 
 -- | Always choose the last constructor.
-rightMost :: Unfoldable t => t ()
-rightMost = runIdentity $ getR unfold_
+rightMost :: Unfoldable t => Maybe (t ())
+rightMost = getDualA unfold_
 
 -- | Generate all the values depth first.
 allDepthFirst :: Unfoldable t => [t ()]
@@ -109,10 +112,15 @@
 allBreadthFirst :: Unfoldable t => [t ()]
 allBreadthFirst = unfoldBF_
 
--- | Generate a random value, can be used as default instance for Random.
-randomValue :: (R.Random a, R.RandomGen g, Unfoldable t) => g -> (t a, g)
-randomValue = runState . getRandom . unfold . Random . state $ R.random
+-- | Generate a random value, can be used as default instance for 'R.Random'.
+randomDefault :: (R.Random a, R.RandomGen g, Unfoldable t) => g -> (t a, g)
+randomDefault = runState . getRandom . unfold . Random . state $ R.random
 
+-- | Provides a QuickCheck generator, can be used as default instance for 'Arbitrary'.
+arbitraryDefault :: (Arbitrary a, Unfoldable t) => Gen (t a)
+arbitraryDefault = MkGen $ \r n -> let Arb _ f = unfold arbUnit in 
+  fromMaybe (error "Failed to generate a value.") (f r (n + 1))
+
 instance Unfoldable [] where
   unfold f = choose 
     [ pure []
@@ -135,16 +143,16 @@
   unfold f = (,) <$> boundedEnum <*> f
 
 instance Unfoldable Identity where
-  unfold f = Identity <$> f
+  unfold = fmap Identity
 
 instance (Bounded a, Enum a) => Unfoldable (Constant a) where
-  unfold _ = Constant <$> boundedEnum
+  unfold = fmap Constant . const boundedEnum
   
 instance (Unfoldable p, Unfoldable q) => Unfoldable (Product p q) where
   unfold f = Pair <$> unfold f <*> unfold f
 
 instance (Unfoldable p, Unfoldable q) => Unfoldable (Compose p q) where
-  unfold f = Compose <$> unfold (unfold f)
+  unfold = fmap Compose . unfold . unfold
 
 instance Unfoldable f => Unfoldable (Reverse f) where
-  unfold f = Reverse <$> getReverse (unfold (Reverse f))
+  unfold = fmap Reverse . getDualA . unfold . DualA
diff --git a/src/Data/Unfolder.hs b/src/Data/Unfolder.hs
--- a/src/Data/Unfolder.hs
+++ b/src/Data/Unfolder.hs
@@ -9,8 +9,9 @@
 -- Portability :  non-portable
 --
 -- Unfolders provide a way to unfold data structures.
--- They are applicative functors that can perform a choice.
--- (Which is basically @Alternative@ without @empty@.)
+-- They are basically 'Alternative' instances, but the 'choose' method
+-- allows the unfolder to do something special for the recursive positions
+-- of the data structure.
 -----------------------------------------------------------------------------
 {-# LANGUAGE 
     ScopedTypeVariables
@@ -21,46 +22,62 @@
   
   -- * Unfolder
     Unfolder(..)
-  , chooseAltDefault
   , chooseMonadDefault
   
   , boundedEnum
   
   -- ** Unfolder instances
-  , Left(..)
-  , Right(..)
+  , DualA(..)
   , Random(..)
 
   , BFS(..)
   , runBFS
   , packBFS
   
+  , Arb(..)
+  , arbUnit
+  
   ) 
   where 
 
 import Control.Applicative
-import Data.Functor.Identity
+import Control.Monad
+import Control.Arrow (ArrowZero, ArrowPlus)
+
 import Data.Functor.Product
 import Data.Functor.Compose
 import Data.Functor.Reverse
-import Control.Monad.Trans.Cont
+import Control.Applicative.Backwards
+import Control.Applicative.Lift
+import Control.Monad.Trans.Error
+import Control.Monad.Trans.List
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.RWS
 import Control.Monad.Trans.Reader
 import Control.Monad.Trans.State
+import Control.Monad.Trans.Writer
+
 import qualified System.Random as R
-import Data.Maybe (catMaybes)
+import Test.QuickCheck.Arbitrary (Arbitrary(..))
+import Test.QuickCheck.Gen (Gen(..))
 
--- | Unfolders provide a way to unfold data structures. The minimal implementation is 'choose'.
-class Applicative f => Unfolder f where
+import Data.Monoid (Monoid)
+import Data.Maybe (catMaybes, listToMaybe)
+import Data.Foldable (asum)
+import Data.Traversable (traverse)
+
+-- | Unfolders provide a way to unfold data structures.
+-- The methods have default implementations in terms of 'Alternative',
+-- but you can implement 'choose' to act on recursive positions of the
+-- data structure, or simply to provide a faster implementation than 'asum'.
+class Alternative f => Unfolder f where
   -- | Choose one of the values from the list.
   choose :: [f x] -> f x
+  choose = asum
   -- | Given a number 'n', return a number between '0' and 'n - 1'.
   chooseInt :: Int -> f Int
   chooseInt n = choose $ map pure [0 .. n - 1]
 
--- | If an unfolder is an instance of 'Alternative', 'choose' can be implemented in terms of '<|>'.
-chooseAltDefault :: (Alternative f, Unfolder f) => [f x] -> f x
-chooseAltDefault = foldr (<|>) empty
-
 -- | If an unfolder is monadic, 'choose' can be implemented in terms of 'chooseInt'.
 chooseMonadDefault :: (Monad m, Unfolder m) => [m x] -> m x
 chooseMonadDefault ms = chooseInt (length ms) >>= (ms !!)
@@ -72,59 +89,114 @@
     lb = fromEnum (minBound :: a)
     ub = fromEnum (maxBound :: a)
 
-newtype Left x = L { getL :: Identity x } deriving (Functor, Applicative, Monad)
--- | Always choose the first item.
-instance Unfolder Left where
-  choose = head
-  chooseInt _ = pure 0
+-- | Derived instance.
+instance MonadPlus m => Unfolder (WrappedMonad m)
 
-newtype Right x = R { getR :: Identity x } deriving (Functor, Applicative, Monad)
--- | Always choose the last item.
-instance Unfolder Right where
-  choose = last
-  chooseInt n = pure (n - 1)
+-- | Derived instance.
+instance (ArrowZero a, ArrowPlus a) => Unfolder (WrappedArrow a b)
 
 -- | Don't choose but return all items.
 instance Unfolder [] where
   choose = concat
   chooseInt n = [0 .. n - 1]
 
+-- | Always choose the first item.
+instance Unfolder Maybe where
+  choose [] = Nothing
+  choose ms = head ms
+  chooseInt 0 = Nothing
+  chooseInt _ = Just 0
+
+-- | 'DualA' flips the '(<|>)' operator.
+newtype DualA f a = DualA { getDualA :: f a }
+  deriving (Functor, Applicative)
+instance Alternative f => Alternative (DualA f) where
+  empty = DualA empty
+  DualA a <|> DualA b = DualA (b <|> a)
+-- | Reverse the list passed to choose.
+instance Unfolder f => Unfolder (DualA f) where
+  choose = DualA . choose . reverse . map getDualA
+  chooseInt n = DualA $ (\x -> n - 1 - x) <$> chooseInt n
+
 fstP :: Product p q a -> p a
 fstP (Pair p _) = p
 
 sndP :: Product p q a -> q a
 sndP (Pair _ q) = q
 
+-- | Derived instance.
 instance (Unfolder p, Unfolder q) => Unfolder (Product p q) where
   choose ps = Pair (choose $ map fstP ps) (choose $ map sndP ps)
   chooseInt n = Pair (chooseInt n) (chooseInt n)
 
+-- | Derived instance.
 instance (Unfolder p, Applicative q) => Unfolder (Compose p q) where
   choose = Compose . choose . map getCompose
   chooseInt n = Compose $ pure <$> chooseInt n
 
-instance Unfolder m => Unfolder (Reverse m) where
-  choose = Reverse . choose . reverse . map getReverse
-  chooseInt n = Reverse $ (\x -> n - 1 - x) <$> chooseInt n
+-- | Derived instance.
+instance Unfolder f => Unfolder (Reverse f) where
+  choose = Reverse . choose . map getReverse
+  chooseInt n = Reverse $ chooseInt n
+
+-- | Derived instance.
+instance Unfolder f => Unfolder (Backwards f) where
+  choose = Backwards . choose . map forwards
+  chooseInt n = Backwards $ chooseInt n
+
+-- | Derived instance.
+instance Unfolder f => Unfolder (Lift f)
+
+-- | Derived instance.
+instance (Functor m, Monad m, Error e) => Unfolder (ErrorT e m)
+
+-- | Derived instance.
+instance Applicative f => Unfolder (ListT f) where
+  choose ms = ListT $ concat <$> traverse runListT ms
+  chooseInt n = ListT $ pure [0 .. n - 1]
+
+-- | Derived instance.
+instance (Functor m, Monad m) => Unfolder (MaybeT m) where
+  choose ms = MaybeT $ fmap (listToMaybe . catMaybes) (mapM runMaybeT ms)
+  chooseInt 0 = MaybeT $ return Nothing
+  chooseInt _ = MaybeT $ return (Just 0)
   
-instance (Monad m, Unfolder m) => Unfolder (StateT s m) where
-  choose ms = StateT $ \as -> choose $ map (`runStateT` as) ms
+-- | Derived instance.
+instance (Monoid w, MonadPlus m, Unfolder m) => Unfolder (RWST r w s m) where
+  choose ms = RWST $ \r s -> choose $ map (\m -> runRWST m r s) ms
 
-instance Unfolder m => Unfolder (ContT r m) where
-  choose ms = ContT $ \k -> choose $ map (`runContT` k) ms
+-- | Derived instance.
+instance (MonadPlus m, Unfolder m) => Unfolder (StateT s m) where
+  choose ms = StateT $ \s -> choose $ map (`runStateT` s) ms
 
+-- | Derived instance.
 instance Unfolder m => Unfolder (ReaderT r m) where
   choose ms = ReaderT $ \r -> choose $ map (`runReaderT` r) ms
   
+-- | Derived instance.
+instance (Monoid w, Unfolder m) => Unfolder (WriterT w m) where
+  choose = WriterT . choose . map runWriterT
+
+
+
 newtype Random g m a = Random { getRandom :: StateT g m a } 
   deriving (Functor, Applicative, Monad)
+instance (Functor m, Monad m, R.RandomGen g) => Alternative (Random g m) where
+  empty = choose []
+  a <|> b = choose [a, b]
+instance (Functor m, Monad m, R.RandomGen g) => MonadPlus (Random g m) where
+  mzero = choose []
+  mplus a b = choose [a, b]
 -- | Choose randomly.
 instance (Functor m, Monad m, R.RandomGen g) => Unfolder (Random g m) where
   choose = chooseMonadDefault
+  chooseInt 0 = Random . StateT $ const (fail "Random chooseInt 0")
   chooseInt n = Random . StateT $ return . R.randomR (0, n - 1)
 
+
 -- | Return a generator of values of a given depth.
---   Returns 'Nothing' if there are no values of that depth or deeper.
+-- Returns 'Nothing' if there are no values of that depth or deeper.
+-- The depth is the number of 'choose' calls.
 newtype BFS f x = BFS { getBFS :: Int -> Maybe [f x] }
 
 instance Functor f => Functor (BFS f) where 
@@ -136,6 +208,10 @@
     [ liftA2 (liftA2 (<*>)) (ff i) (fx d) | i <- [0 .. d - 1] ] ++
     [ liftA2 (liftA2 (<*>)) (ff d) (fx i) | i <- [0 .. d] ]
 
+instance Applicative f => Alternative (BFS f) where
+  empty = BFS $ \d -> if d == 0 then Just [] else Nothing
+  BFS fa <|> BFS fb = BFS $ \d -> flattenBFS [fa d, fb d]
+  
 -- | Choose between values of a given depth only.
 instance Applicative f => Unfolder (BFS f) where
   choose ms = BFS $ \d -> if d == 0 then Just [] else flattenBFS (map (`getBFS` (d - 1)) ms)
@@ -150,3 +226,38 @@
 flattenBFS ms = case catMaybes ms of
   [] -> Nothing
   ms' -> Just (concat ms')
+
+
+-- | A variant of Test.QuickCheck.Gen, with failure 
+-- and a count of the number of recursive positions.
+data Arb a = Arb Int (R.StdGen -> Int -> Maybe a)
+
+instance Functor Arb where
+  fmap f (Arb i g) = Arb i $ fmap (fmap (fmap f)) g
+
+instance Applicative Arb where
+  pure = Arb 0 . pure . pure . pure
+  Arb i1 ff <*> Arb i2 fx = Arb (i1 + i2) $
+    \r -> let (r1, r2) = R.split r in liftA2 (<*>) (ff r1) (fx r2)
+
+instance Alternative Arb where
+  empty = Arb 0 (\_ _ -> Nothing)
+  Arb ia fa <|> Arb ib fb = Arb ((ia + ib + 1) `div` 2) $
+    \r n -> let (r1, r2) = R.split r in flattenArb r1 [fa r2 n, fb r2 n]
+
+-- | Limit the depth of the generated data structure by 
+-- dividing the given size by the number of recursive positions.
+instance Unfolder Arb where
+  choose ms = Arb 1 g
+    where
+      g _ 0 = Nothing
+      g r n = let (r1, r2) = R.split r in 
+        flattenArb r1 $ map (\(Arb i f) -> f r2 (n `div` max i 1)) ms
+
+flattenArb :: R.StdGen -> [Maybe a] -> Maybe a
+flattenArb r ms = case catMaybes ms of
+  [] -> Nothing
+  ms' -> Just $ ms' !! fst (R.randomR (0, length ms' - 1) r)
+
+arbUnit :: Arbitrary a => Arb a
+arbUnit = Arb 0 (\r n -> Just $ unGen arbitrary r n)
diff --git a/src/Data/Unfolder/Arbitrary.hs b/src/Data/Unfolder/Arbitrary.hs
deleted file mode 100644
--- a/src/Data/Unfolder/Arbitrary.hs
+++ /dev/null
@@ -1,39 +0,0 @@
-{-# LANGUAGE 
-    ScopedTypeVariables
-  , GeneralizedNewtypeDeriving
-  #-}
-module Data.Unfolder.Arbitrary where
-  
-import Control.Applicative
-import Data.Unfoldable
-import Data.Unfolder
-import Test.QuickCheck.Arbitrary
-import Test.QuickCheck.Gen
-
-import Control.Monad.Trans.Reader
-import Data.Functor.Constant
-import Data.Monoid (Sum(..))
-
--- This is somewhat of a hack. It assumes that choose always chooses from a list of Gen (t a),
--- which is true at the top-level, but might not be when recursing.
-
-newtype CountPos a = CountPos { getCountPos :: Constant (Sum Int, Sum Int, [(Int, Int)]) a }
-  deriving (Functor, Applicative)
-instance Unfolder CountPos where
-  choose ms = CountPos . Constant $ 
-    (Sum 0, Sum 1, map (\(CountPos (Constant (Sum c, Sum r, _))) -> (c, r)) ms)
-
-newtype Arb a = Arb { getArb :: ReaderT [(Int, Int)] Gen a }
-  deriving (Functor, Applicative)
-instance Unfolder Arb where
-  choose ms = Arb (ReaderT f)
-    where 
-      f poss = sized (\n -> oneof . map (resz n) . filter ((<= n) . fst . fst) . zip poss $ ms)
-        where
-          resz n ((c, r), Arb (ReaderT g)) = resize ((n - c) `div` max r 1) (g poss)
-
-arbitraryDefault :: forall t a. (Unfoldable t, Arbitrary a) => Gen (t a)
-arbitraryDefault = flip runReaderT poss . getArb $ unfold (Arb . ReaderT $ const arbitrary)
-  where
-    CountPos (Constant (_, _, poss)) = 
-      unfold (CountPos $ Constant (Sum 1, Sum 0, [])) :: CountPos (t ())
diff --git a/unfoldable.cabal b/unfoldable.cabal
--- a/unfoldable.cabal
+++ b/unfoldable.cabal
@@ -1,5 +1,5 @@
 Name:                 unfoldable
-Version:              0.4.0
+Version:              0.5.0
 Synopsis:             Class of data structures that can be unfolded.
 Description:          Just as there's a Foldable class, there should also be an Unfoldable class. 
                       .
@@ -24,7 +24,6 @@
 
 Extra-Source-Files:
   examples/*.hs
-  src/Data/Unfolder/Arbitrary.hs
 
 Library
   HS-Source-Dirs:  src
@@ -37,6 +36,7 @@
       base         >= 4   && < 5 
     , transformers >= 0.3 && < 0.4
     , random       >= 1.0 && < 1.1
+    , QuickCheck   >= 2.4 && < 2.5
 
 source-repository head
   type:     git
