diff --git a/Data/Supply.hs b/Data/Supply.hs
--- a/Data/Supply.hs
+++ b/Data/Supply.hs
@@ -21,14 +21,15 @@
   , newSupply
   , newEnumSupply
   , newNumSupply
-  , unsafeNewIntSupply
 
+  , newDupableSupply
+  , newDupableEnumSupply
+  , newDupableNumSupply
+
   -- * Obtaining values from supplies
   , supplyValue
 
   -- * Generating new supplies from old
-  , supplyLeft
-  , supplyRight
   , modifySupply
   , split
   , split2
@@ -36,105 +37,100 @@
   , split4
   ) where
 
--- Usinga an IORef is thread-safe because we update it with 'atomicModifyIORef'.
--- XXX: Is the atomic necessary?
-import Data.IORef(IORef,newIORef,atomicModifyIORef)
-import System.IO.Unsafe(unsafePerformIO,unsafeInterleaveIO)
+-- NOTE: Using an IORef is thread-safe because we update it with
+-- 'atomicModifyIORef'.  We need the 'atomicModifyRef' because multiple
+-- threads may be evaluating different supplies that share the same
+-- 'IORef' and we need to avoid race conditions.  This is the case for
+-- both the normal and the dupable supplies.
+import Data.IORef(newIORef,atomicModifyIORef)
+import System.IO.Unsafe(unsafeInterleaveIO)
 
 #if __GLASGOW_HASKELL__ >= 608
-import GHC.IOBase(unsafeDupableInterleaveIO,unsafeDupablePerformIO)
+import GHC.IOBase(unsafeDupableInterleaveIO)
 #else
 unsafeDupableInterleaveIO :: IO a -> IO a
 unsafeDupableInterleaveIO = unsafeInterleaveIO
-
-unsafeDupablePerformIO :: IO a -> a
-unsafeDupablePerformIO = unsafePerformIO
 #endif
 
 -- Basics ----------------------------------------------------------------------
 
 -- | A type that can be used to generate values on demand.
--- A supply may be turned into two different supplies by using
--- the functions 'supplyLeft' and 'supplyRight'.
-data Supply a = Node
-  { -- | Get the value of a supply.  This function, together with
-    -- 'modifySupply' forms a comonad on 'Supply'.
-    supplyValue :: a
+data Supply a = Node a (Supply a) (Supply a)
 
-  -- | Generate a new supply.  This supply is different from the one
-  -- generated with 'supplyRight'.
-  , supplyLeft  :: Supply a
+-- | Get the value of a supply.  This function, together with
+-- 'modifySupply' forms a comonad on 'Supply'.
+supplyValue    :: Supply a -> a
+supplyValue (Node a _ _) = a
 
-  -- | Generate a new supply. This supply is different from the one
-  -- generated with 'supplyLeft'.
-  , supplyRight :: Supply a
-  }
+-- | Generate an infinite list of supplies.
+split          :: Supply a -> [Supply a]
+split (Node _ s1 s2)  = s1 : split s2
 
+-- | Split a supply into two different supplies.
+-- The resulting supplies are different from the input supply.
+split2         :: Supply a -> (Supply a, Supply a)
+split2 (Node _ s1 s2) = (s1,s2)
+
+-- | Split a supply into three different supplies.
+split3         :: Supply a -> (Supply a, Supply a, Supply a)
+split3 (Node _ s1 (Node _ s2 s3)) = (s1,s2,s3)
+
+-- | Split a supply into four different supplies.
+split4         :: Supply a -> (Supply a, Supply a, Supply a, Supply a)
+split4 (Node _ s1 (Node _ s2 (Node _ s3 s4))) = (s1,s2,s3,s4)
+
+
+
+
 instance Functor Supply where
   fmap f s = modifySupply s (f . supplyValue)
 
 
-{-# INLINE genericNewSupply #-}
-genericNewSupply :: b -> (IORef b -> IO a) -> IO (Supply a)
-genericNewSupply start genSym = gen =<< newIORef start
-  where gen r = unsafeInterleaveIO
-              $ do ls <- gen r
-                   rs <- gen r
-                   return (Node (unsafePerformIO (genSym r)) ls rs)
-
 -- | Creates a new supply of values.
 -- The arguments specify how to generate values:
 -- the first argument is an initial value, the
 -- second specifies how to generate a new value from an existing one.
-newSupply      :: a -> (a -> a) -> IO (Supply a)
-newSupply x f   = genericNewSupply (iterate f x) listGenSym
+{-# INLINE newSupply #-}
+newSupply :: a -> (a -> a) -> IO (Supply a)
+newSupply start next = gen =<< newIORef start
+  where gen r = unsafeInterleaveIO
+              $ do v  <- unsafeInterleaveIO (atomicModifyIORef r upd)
+                   ls <- gen r
+                   rs <- gen r
+                   return (Node v ls rs)
+        upd a = let b = next a in seq b (b, a)
 
-{-# SPECIALIZE newEnumSupply :: IO (Supply Int) #-}
--- | A supply of values that are in the 'Enum' class.
--- The initial value is @toEnum 0@, new values are generates with 'succ'.
-newEnumSupply  :: (Enum a) => IO (Supply a)
-newEnumSupply   = genericNewSupply (toEnum 0) enumGenSym
 
-{-# SPECIALIZE newNumSupply :: IO (Supply Int) #-}
--- | A supply of values that are in the 'Num' class.
--- The initial value is 0, new values are generated by adding 1.
-newNumSupply   :: (Num a) => IO (Supply a)
-newNumSupply    = genericNewSupply 0 numGenSym
-
--- | Create a supply of ints.
--- WARNING: In general, this is not thread safe!
--- It should be OK, as long as the supply is not accessed by different threads.
--- So, if you are in a multi-threaded setting, first split
--- the supply, and give /different/ supply values to the different threads.
-unsafeNewIntSupply :: IO (Supply Int)
-unsafeNewIntSupply = gen =<< newIORef 0
+-- | Create a new supply of values.
+-- WARNING: This version is faster then 'newSupply' but it is not completely
+-- thread safe, so use only if performance is an issue!
+--
+-- Rules for using the generated supplies:
+--   * Supply splitting should be evaluated in a single thread.
+--     For example, use "case" with 'split2' to force the splitting
+--     of a supply.
+--   * Different threads should work with different supplies.
+--     For example, one could (strictly) split a supply, and then
+--     fork new threads with the resulting supplies.
+{-# INLINE newDupableSupply #-}
+newDupableSupply :: a -> (a -> a) -> IO (Supply a)
+newDupableSupply start next = gen =<< newIORef start
   where gen r = unsafeDupableInterleaveIO
-              $ do ls <- gen r
+              $ do v  <- unsafeDupableInterleaveIO (atomicModifyIORef r upd)
+                   ls <- gen r
                    rs <- gen r
-                   return (Node (unsafeDupablePerformIO (enumGenSym r)) ls rs)
-
-
+                   return (Node v ls rs)
+        upd a = let b = next a in seq b (b, a)
 
 
--- Different ways to generate new values:
-listGenSym     :: IORef [a] -> IO a
-listGenSym r    = atomicModifyIORef r (\(a:as) -> (as,a))
-
-enumGenSym     :: Enum a => IORef a -> IO a
-enumGenSym r    = atomicModifyIORef r (\a -> let n = succ a in seq n (n,a))
-
-numGenSym      :: Num a => IORef a -> IO a
-numGenSym r     = atomicModifyIORef r (\a -> let n = 1 + a in seq n (n,a))
-
+-- XXX: Is the strictness of 'modifySupply' OK?
 
 -- | Generate a new supply by systematically applying a function
 -- to an existing supply.  This function, together with 'supplyValue'
 -- form a comonad on 'Supply'.
 modifySupply :: Supply a -> (Supply a -> b) -> Supply b
-modifySupply s f = Node { supplyValue = f s
-                        , supplyLeft  = modifySupply (supplyLeft s) f
-                        , supplyRight = modifySupply (supplyRight s) f
-                        }
+modifySupply s f = Node (f s) (modifySupply l f) (modifySupply r f)
+  where Node _ l r = s
 
 -- (Supply, supplyValue, modifySupply) form a comonad:
 {-
@@ -146,26 +142,31 @@
 -}
 
 
--- Derived functions -----------------------------------------------------------
+{-# SPECIALIZE newEnumSupply :: IO (Supply Int) #-}
+-- | A supply of values that are in the 'Enum' class.
+-- The initial value is @toEnum 0@, new values are generates with 'succ'.
+newEnumSupply        :: (Enum a) => IO (Supply a)
+newEnumSupply         = newSupply (toEnum 0) succ
 
--- | Generate an infinite list of supplies by using 'supplyLeft' and
--- 'supplyRight' repeatedly.
-split          :: Supply a -> [Supply a]
-split s         = supplyLeft s : split (supplyRight s)
+{-# SPECIALIZE newNumSupply :: IO (Supply Int) #-}
+-- | A supply of values that are in the 'Num' class.
+-- The initial value is 0, new values are generated by adding 1.
+newNumSupply         :: (Num a) => IO (Supply a)
+newNumSupply          = newSupply 0 (1+)
 
--- | Split a supply into two different supplies.
--- The resulting supplies are different from the input supply.
-split2         :: Supply a -> (Supply a, Supply a)
-split2 s        = (supplyLeft s, supplyRight s)
+{-# SPECIALIZE newDupableEnumSupply :: IO (Supply Int) #-}
+-- | A supply of values that are in the 'Enum' class.
+-- The initial value is @toEnum 0@, new values are generates with 'succ'.
+-- WARNING: See comment on 'newDupableSupply'
+newDupableEnumSupply :: (Enum a) => IO (Supply a)
+newDupableEnumSupply  = newDupableSupply (toEnum 0) succ
 
--- | Split a supply into three different supplies.
-split3         :: Supply a -> (Supply a, Supply a, Supply a)
-split3 s        = let s1 : s2 : s3 : _ = split s
-                  in (s1,s2,s3)
+{-# SPECIALIZE newDupableNumSupply :: IO (Supply Int) #-}
+-- | A supply of values that are in the 'Num' class.
+-- The initial value is 0, new values are generated by adding 1.
+-- WARNING: See comment on 'newDupableSupply'
+newDupableNumSupply  :: (Num a) => IO (Supply a)
+newDupableNumSupply   = newDupableSupply 0 (1+)
 
--- | Split a supply into four different supplies.
-split4         :: Supply a -> (Supply a, Supply a, Supply a, Supply a)
-split4 s        = let s1 : s2 : s3 : s4 : _ = split s
-                  in (s1,s2,s3,s4)
 
 
diff --git a/value-supply.cabal b/value-supply.cabal
--- a/value-supply.cabal
+++ b/value-supply.cabal
@@ -1,9 +1,11 @@
 Name:           value-supply
-Version:        0.4
+Version:        0.5
+Homepage:       http://github.com/yav/value-supply
 License:        BSD3
 License-file:   LICENSE
 Author:         Iavor S. Diatchki
 Maintainer:     iavor.diatchki@gmail.com
+
 Category:       Data
 Synopsis: A library for generating values without having to thread state.
 Description:
