diff --git a/examples/btree.hs b/examples/btree.hs
new file mode 100644
--- /dev/null
+++ b/examples/btree.hs
@@ -0,0 +1,24 @@
+import Control.Applicative
+import Data.Unfoldable
+import Data.Unfolder
+
+import Data.Maybe
+import System.Random
+
+
+data TB a = LB a | BB (TB (a, a)) deriving Show
+
+instance Unfoldable TB where
+  unfold fa = choose
+    [ LB <$> fa
+    , BB <$> unfold ((,) <$> fa <*> fa)
+    ]
+
+btree8 :: TB Int
+btree8 = fromJust $ fromList [0..7]
+
+btreeShapes :: [TB ()]
+btreeShapes = take 5 unfold_
+
+randomBTree :: IO (TB Bool)
+randomBTree = getStdRandom randomValue
diff --git a/examples/tree.hs b/examples/tree.hs
new file mode 100644
--- /dev/null
+++ b/examples/tree.hs
@@ -0,0 +1,25 @@
+import Control.Applicative
+import Data.Unfoldable
+import Data.Unfolder
+
+import Data.Maybe
+import System.Random
+
+
+data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a) deriving Show
+
+instance Unfoldable Tree where
+  unfold fa = choose
+    [ pure Empty
+    , Leaf <$> fa
+    , Node <$> unfold fa <*> fa <*> unfold fa
+    ]
+    
+tree7 :: Tree Int
+tree7 = fromJust $ fromList [0..6]
+
+treeShapes :: [Tree ()]
+treeShapes = take 10 unfoldBF_
+
+randomTree :: IO (Tree Bool)
+randomTree = getStdRandom randomValue
diff --git a/src/Data/Unfoldable.hs b/src/Data/Unfoldable.hs
--- a/src/Data/Unfoldable.hs
+++ b/src/Data/Unfoldable.hs
@@ -1,25 +1,37 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Unfoldable
+-- Copyright   :  (c) Sjoerd Visscher 2012
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  sjoerd@w3future.com
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- Class of data structures that can be unfolded.
+-----------------------------------------------------------------------------
 module Data.Unfoldable 
   (
-    Unfolder(..)
   
-  , Unfoldable(..)
+  -- * Unfoldable
+    Unfoldable(..)
   , unfold_
   , unfoldBF
   , unfoldBF_
   
   -- ** Specific unfolds
+  , unfoldr
+  , fromList
   , leftMost
   , rightMost
   , allDepthFirst
   , allBreadthFirst
-  , randomDefault
-  , fromList
+  , randomValue
   
   ) 
   where
     
 import Control.Applicative
-import Control.Monad
 import Data.Unfolder
 import Data.Functor.Compose
 import Data.Functor.Constant
@@ -28,7 +40,7 @@
 import Data.Functor.Reverse
 import Control.Monad.Trans.State
 import qualified System.Random as R
-import Data.Maybe (listToMaybe)
+import Data.Maybe
 
 -- | Data structures that can be unfolded.
 --
@@ -51,18 +63,36 @@
   -- | Given a way to generate elements, return a way to generate structures containing those elements.
   unfold :: Unfolder f => f a -> f (t a)
 
--- | Unfold the structure, always using '()' as elements.
+-- | Unfold the structure, always using @()@ as elements.
 unfold_ :: (Unfoldable t, Unfolder f) => f (t ())
 unfold_ = unfold (pure ())
 
--- | Breadth-first unfold
-unfoldBF :: (Unfoldable t, Unfolder f, Alternative f) => f a -> f (t a)
+-- | Breadth-first unfold, which orders the result by the number of 'choose' calls.
+unfoldBF :: (Unfoldable t, Unfolder f) => f a -> f (t a)
 unfoldBF = runBFS . unfold . packBFS
 
--- | Unfold the structure breadth-first, always using '()' as elements.
-unfoldBF_ :: (Unfoldable t, Unfolder f, Alternative f) => f (t ())
+-- | Unfold the structure breadth-first, always using @()@ as elements.
+unfoldBF_ :: (Unfoldable t, Unfolder f) => f (t ())
 unfoldBF_ = unfoldBF (pure ())
 
+-- | @unfoldr@ builds a data structure from a seed value. It can be specified as:
+-- 
+-- > unfoldr f z == fromList (Data.List.unfoldr f z)
+unfoldr :: Unfoldable t => (b -> Maybe (a, b)) -> b -> Maybe (t a)
+unfoldr f z = terminate . flip runStateT z . unfoldBF . StateT $ maybeToList . f
+  where
+    terminate [] = Nothing
+    terminate ((t, b):ts) = if isNothing (f b) then Just t else terminate ts
+
+-- | Create a data structure using the list as input.
+-- This can fail because there might not be a data structure with the same number
+-- of element positions as the number of elements in the list.
+fromList :: Unfoldable t => [a] -> Maybe (t a)
+fromList = unfoldr uncons
+  where
+    uncons [] = Nothing
+    uncons (a:as) = Just (a, as)
+
 -- | Always choose the first constructor.
 leftMost :: Unfoldable t => t ()
 leftMost = runIdentity $ getL unfold_
@@ -80,20 +110,8 @@
 allBreadthFirst = unfoldBF_
 
 -- | Generate a random value, can be used as default instance for Random.
-randomDefault :: (R.Random a, R.RandomGen g, Unfoldable t) => g -> (t a, g)
-randomDefault = runState . getRandom . unfold . Random . state $ R.random
-
-fromList' :: (Unfolder f, MonadPlus f, Unfoldable t) => [a] -> f (t a, [a])
-fromList' as = flip runStateT as . unfoldBF . StateT $ uncons
-  where
-    uncons [] = mzero
-    uncons (a:as') = return (a, as')
-
--- | Create a data structure using the list as input.
---   This can fail because there might not be a data structure with the same number
---   of element positions as the number of elements in the list.
-fromList :: Unfoldable t => [a] -> Maybe (t a)
-fromList as = listToMaybe [ t | (t, []) <- fromList' as ]
+randomValue :: (R.Random a, R.RandomGen g, Unfoldable t) => g -> (t a, g)
+randomValue = runState . getRandom . unfold . Random . state $ R.random
 
 instance Unfoldable [] where
   unfold f = choose 
diff --git a/src/Data/Unfolder.hs b/src/Data/Unfolder.hs
--- a/src/Data/Unfolder.hs
+++ b/src/Data/Unfolder.hs
@@ -1,14 +1,32 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Unfolder
+-- Copyright   :  (c) Sjoerd Visscher 2012
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  sjoerd@w3future.com
+-- Stability   :  experimental
+-- 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@.)
+-----------------------------------------------------------------------------
 {-# LANGUAGE 
     ScopedTypeVariables
   , GeneralizedNewtypeDeriving
   #-}
 module Data.Unfolder 
   (
+  
+  -- * Unfolder
     Unfolder(..)
-  , chooseDefault
+  , chooseAltDefault
+  , chooseMonadDefault
   
   , boundedEnum
   
+  -- ** Unfolder instances
   , Left(..)
   , Right(..)
   , Random(..)
@@ -29,7 +47,6 @@
 import Control.Monad.Trans.Reader
 import Control.Monad.Trans.State
 import qualified System.Random as R
-import Data.Foldable (asum)
 import Data.Maybe (catMaybes)
 
 -- | Unfolders provide a way to unfold data structures. The minimal implementation is 'choose'.
@@ -40,9 +57,13 @@
   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'.
-chooseDefault :: (Monad m, Unfolder m) => [m x] -> m x
-chooseDefault ms = chooseInt (length ms) >>= (ms !!)
+chooseMonadDefault :: (Monad m, Unfolder m) => [m x] -> m x
+chooseMonadDefault ms = chooseInt (length ms) >>= (ms !!)
 
 -- | If a datatype is bounded and enumerable, we can use 'chooseInt' to generate a value.
 boundedEnum :: forall f a. (Unfolder f, Bounded a, Enum a) => f a
@@ -75,16 +96,16 @@
 sndP (Pair _ q) = q
 
 instance (Unfolder p, Unfolder q) => Unfolder (Product p q) where
-  chooseInt n = Pair (chooseInt n) (chooseInt n)
   choose ps = Pair (choose $ map fstP ps) (choose $ map sndP ps)
+  chooseInt n = Pair (chooseInt n) (chooseInt n)
 
 instance (Unfolder p, Applicative q) => Unfolder (Compose p q) where
-  chooseInt n = Compose $ pure <$> chooseInt n
   choose = Compose . choose . map getCompose
+  chooseInt n = Compose $ pure <$> chooseInt n
 
 instance Unfolder m => Unfolder (Reverse m) where
-  chooseInt n = Reverse $ (\x -> n - 1 - x) <$> chooseInt n
   choose = Reverse . choose . reverse . map getReverse
+  chooseInt n = Reverse $ (\x -> n - 1 - x) <$> chooseInt n
   
 instance (Monad m, Unfolder m) => Unfolder (StateT s m) where
   choose ms = StateT $ \as -> choose $ map (`runStateT` as) ms
@@ -99,35 +120,33 @@
   deriving (Functor, Applicative, Monad)
 -- | Choose randomly.
 instance (Functor m, Monad m, R.RandomGen g) => Unfolder (Random g m) where
-  choose = chooseDefault
+  choose = chooseMonadDefault
   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.
-newtype BFS f x = BFS { getBFS :: Int -> Maybe (f x) }
+newtype BFS f x = BFS { getBFS :: Int -> Maybe [f x] }
 
 instance Functor f => Functor (BFS f) where 
-  fmap f = BFS . (fmap (fmap f) .) . getBFS
+  fmap f = BFS . (fmap (map (fmap f)) .) . getBFS
 
-instance Alternative f => Applicative (BFS f) where
+instance Applicative f => Applicative (BFS f) where
   pure = packBFS . pure
-  BFS ff <*> BFS fx = BFS $ \d -> flattenBFS asum $
-    [ (<*>) <$> ff i <*> fx d | i <- [0 .. d - 1] ] ++
-    [ (<*>) <$> ff d <*> fx i | i <- [0 .. d] ]
+  BFS ff <*> BFS fx = BFS $ \d -> flattenBFS $
+    [ liftA2 (liftA2 (<*>)) (ff i) (fx d) | i <- [0 .. d - 1] ] ++
+    [ liftA2 (liftA2 (<*>)) (ff d) (fx i) | i <- [0 .. d] ]
 
 -- | Choose between values of a given depth only.
-instance (Alternative f, Unfolder f) => Unfolder (BFS f) where
-  choose ms = BFS $ \d -> if d == 0 
-    then Just empty
-    else flattenBFS choose (map (`getBFS` (d - 1)) ms)
+instance Applicative f => Unfolder (BFS f) where
+  choose ms = BFS $ \d -> if d == 0 then Just [] else flattenBFS (map (`getBFS` (d - 1)) ms)
 
-runBFS :: Alternative f => BFS f x -> f x
-runBFS (BFS f) = loop 0 where loop d = maybe empty (<|> loop (d + 1)) (f d)
+runBFS :: Unfolder f => BFS f x -> f x
+runBFS (BFS f) = choose (loop 0) where loop d = maybe [] (++ loop (d + 1)) (f d)
 
 packBFS :: f x -> BFS f x
-packBFS r = BFS $ \d -> if d == 0 then Just r else Nothing
+packBFS r = BFS $ \d -> if d == 0 then Just [r] else Nothing
 
-flattenBFS :: ([a] -> a) -> [Maybe a] -> Maybe a
-flattenBFS f ms = case catMaybes ms of
+flattenBFS :: [Maybe [a]] -> Maybe [a]
+flattenBFS ms = case catMaybes ms of
   [] -> Nothing
-  ms' -> Just (f ms')
+  ms' -> Just (concat ms')
diff --git a/src/Data/Unfolder/Arbitrary.hs b/src/Data/Unfolder/Arbitrary.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Unfolder/Arbitrary.hs
@@ -0,0 +1,39 @@
+{-# 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,16 +1,19 @@
 Name:                 unfoldable
-Version:              0.3.0
+Version:              0.4.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. 
+                      .
                       This package provides one. Example unfolds are:
                       .
                       * Random values
+                      .
                       * Enumeration of all values (depth-first or breadth-first)
+                      .
                       * Convert from a list
                       .
-                      The package provides examples in the examples directory.
+                      Some examples can be found in the examples directory.
 Homepage:             https://github.com/sjoerdvisscher/unfoldable
-Bug-reports:          https://github.com/sjoerdvisscher/data-category/issues
+Bug-reports:          https://github.com/sjoerdvisscher/unfoldable/issues
 License:              BSD3
 License-file:         LICENSE
 Author:               Sjoerd Visscher
@@ -18,6 +21,10 @@
 Category:             Generics
 Build-type:           Simple
 Cabal-version:        >= 1.6
+
+Extra-Source-Files:
+  examples/*.hs
+  src/Data/Unfolder/Arbitrary.hs
 
 Library
   HS-Source-Dirs:  src
