diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c)2012, Sjoerd Visscher
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Sjoerd Visscher nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/src/Data/Splittable.hs b/src/Data/Splittable.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Splittable.hs
@@ -0,0 +1,74 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+module Data.Splittable (
+    Splittable(..)
+  
+  , boundedEnum
+  
+  , Left(..)
+  , Right(..)
+  
+  ) where 
+
+import qualified System.Random as R
+import Data.List (mapAccumR)
+
+-- | Splittable datatypes are datatypes that can be used as seeds for unfolds.
+class Splittable s where
+  -- | @split n s@ splits the seed @s@ in @n@ seeds. 
+  split  :: Int -> s -> [s]
+  -- | @choose fs s@ uses part of the seed @s@ to choose a function from the list @fs@,
+  -- and passes the remainder to that function.
+  choose :: [s -> x] -> s -> x
+  -- | Convert the seed value to an @int@.
+  getInt :: s -> Int
+
+-- | If a datatype is bounded and enumerable, we can use 'getInt' to produce a value from a seed.
+boundedEnum :: forall s a. (Splittable s, Bounded a, Enum a) => s -> a
+boundedEnum s = toEnum $ (getInt s `mod` (1 + ub - lb)) + lb
+  where 
+    lb = fromEnum (minBound :: a)
+    ub = fromEnum (maxBound :: a)
+
+data Left = L
+instance Splittable Left where
+  split = replicate
+  choose fs = head fs
+  getInt L = 0
+
+data Right = R
+instance Splittable Right where
+  split = replicate
+  choose fs = last fs
+  getInt R = maxBound
+
+instance Splittable R.StdGen where
+  split 0 _ = []
+  split 1 s = [s]
+  split n s = let (s1, s2) = R.split s in s1 : split (n - 1) s2 
+  choose fs s = let (n, s') = R.next s in fs !! (n `mod` length fs) $ s'
+  getInt = fst . R.next
+
+instance Splittable Integer where
+  split n t = split' 1 (t, replicate n 0)
+    where
+      split' _ (0, l) = l
+      split' p (s, l) = split' (p * 2) $ mapAccumR (\s' i -> let (s'', b) = s' `divMod` 2 in (s'', i + b * p)) s l
+  choose fs s = let (s', n) = s `divMod` toInteger (length fs) in fs !! fromInteger n $ s'
+  getInt = fromInteger
+
+instance (Splittable a, Splittable b) => Splittable (a, b) where
+  split n (a, b) = zip (split n a) (split n b)
+  choose = uncurry . choose . map curry
+  getInt (a, b) = go (getInt a) (getInt b)
+    where
+      go 0 0 = 0
+      go m n = go m' n' * 4 + mb * 2 + nb
+        where
+          (m', mb) = m `divMod` 2
+          (n', nb) = n `divMod` 2
+
+instance (Splittable a, Splittable b) => Splittable (Either a b) where
+  split n   = either (map Left . split n) (map Right . split n)
+  choose fs = either (choose (map (. Left) fs)) (choose (map (. Right) fs))
+  getInt (Left a) = getInt a * 2
+  getInt (Right a) = getInt a * 2 + 1
diff --git a/src/Data/Unfoldable.hs b/src/Data/Unfoldable.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Unfoldable.hs
@@ -0,0 +1,78 @@
+module Data.Unfoldable (
+
+    Unfoldable(..)
+
+  -- ** Specific unfolds
+  , unfold
+  , leftMost
+  , rightMost
+
+  -- ** Helper functions
+  , spread
+  , to
+
+  ) where
+    
+import Control.Applicative
+import Control.Monad.Trans.State
+import Data.Splittable
+
+-- | Data structures that can be unfolded.
+--
+-- For example, given a data type
+--
+-- > data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)
+--
+-- a suitable instance would be
+--
+-- > instance Unfoldable Tree where
+-- >   unfoldMap f = choose
+-- >     [ spread $ pure Empty
+-- >     , spread $ Leaf <$> to f
+-- >     , spread $ Node <$> to (unfoldMap f) <*> to f <*> to (unfoldMap f)
+-- >     ]
+--
+-- i.e. it follows closely the instance for 'Traversable', with the addition of 'choose', 'spread' and 'to'.
+-- 
+-- The instance can be simplified to:
+--
+-- > instance Unfoldable Tree where
+-- >   unfoldMap f = choose
+-- >     [ const Empty
+-- >     , Leaf . f
+-- >     , spread $ Node <$> to (unfoldMap f) <*> to f <*> to (unfoldMap f)
+-- >     ]
+class Unfoldable f where
+  -- | Given a function to generate an element from a seed, 
+  -- and an initial seed, generate a structure.
+  unfoldMap :: Splittable s => (s -> a) -> s -> f a
+
+unfold :: (Unfoldable f, Splittable s) => s -> f s
+unfold = unfoldMap id
+
+leftMost :: Unfoldable f => f ()
+leftMost = unfoldMap (const ()) L
+
+rightMost :: Unfoldable f => f ()
+rightMost = unfoldMap (const ()) R
+
+spread :: Splittable s => State ([s], Int) a -> s -> a
+spread f s = let (a, (_, i)) = runState f (split i s, 0) in a
+
+to :: (s -> a) -> State ([s], Int) a
+to f = state $ \(ss, i) -> (f (head ss), (tail ss, i + 1))
+
+instance Unfoldable [] where
+  unfoldMap f = go
+    where
+      go = choose [const [], spread $ (:) <$> to f <*> to go]
+
+instance Unfoldable Maybe where
+  unfoldMap f = choose [const Nothing, Just . f]
+
+instance (Bounded a, Enum a) => Unfoldable (Either a) where
+  unfoldMap f = choose [Left . boundedEnum, Right . f]
+
+instance (Bounded a, Enum a) => Unfoldable ((,) a) where
+  unfoldMap f = spread $ (,) <$> to boundedEnum <*> to f
+
diff --git a/unfoldable.cabal b/unfoldable.cabal
new file mode 100644
--- /dev/null
+++ b/unfoldable.cabal
@@ -0,0 +1,27 @@
+Name:                unfoldable
+Version:             0.0.0
+Synopsis:            Class of data structures that can be unfolded from a seed value.
+Homepage:            https://github.com/sjoerdvisscher/unfoldable
+License:             BSD3
+License-file:        LICENSE
+Author:              Sjoerd Visscher
+Maintainer:          sjoerd@w3future.com
+Category:            Generics
+Build-type:          Simple
+Cabal-version:       >= 1.6
+
+Library
+  HS-Source-Dirs:  src
+  
+  Exposed-modules:
+    Data.Splittable
+    Data.Unfoldable  
+  
+  Build-depends:
+      base         >= 4   && < 5 
+    , transformers >= 0.2 && < 0.4
+    , random       >= 1.0 && < 1.1
+
+source-repository head
+  type:     git
+  location: git://github.com/sjoerdvisscher/unfoldable.git
