diff --git a/Data/Supply.hs b/Data/Supply.hs
--- a/Data/Supply.hs
+++ b/Data/Supply.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 --------------------------------------------------------------------
 -- |
 -- Module    : Data.Supply
@@ -35,8 +36,15 @@
   ) where
 
 -- Usinga an IORef is thread-safe because we update it with 'atomicModifyIORef'.
-import Data.IORef
+import Data.IORef(IORef,newIORef,atomicModifyIORef)
+
+#if __GLASGOW_HASKELL__ >= 608
+import GHC.IOBase(unsafeDupableInterleaveIO)
+#else
 import System.IO.Unsafe(unsafeInterleaveIO)
+unsafeDupableInterleaveIO :: IO a -> IO a
+unsafeDupableInterleaveIO = unsafeInterleaveIO
+#endif
 
 -- Basics ----------------------------------------------------------------------
 
@@ -60,21 +68,49 @@
 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 = unsafeDupableInterleaveIO
+              $ do v <- unsafeDupableInterleaveIO (genSym r)
+                   ls <- gen r
+                   rs <- gen r
+                   return (Node v 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 = gen =<< newIORef (iterate f x)
+newSupply      :: a -> (a -> a) -> IO (Supply a)
+newSupply x f   = genericNewSupply (iterate f x) listGenSym
 
-  where gen r = do v <- unsafeInterleaveIO (genSym r)
-                   ls <- unsafeInterleaveIO (gen r)
-                   rs <- unsafeInterleaveIO (gen r)
-                   return (Node v ls rs)
+{-# 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
 
-        genSym       :: IORef [a] -> IO a
-        genSym r      = atomicModifyIORef r (\(a:as) -> (as,a))
-                           
+{-# 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
+
+
+-- 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))
+
+
+
 -- | Generate a new supply by systematically applying a function
 -- to an existing supply.  This function, together with 'supplyValue'
 -- form a comonad on 'Supply'.
@@ -95,16 +131,6 @@
 
 
 -- Derived functions -----------------------------------------------------------
-
--- | 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
-
--- | 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+)
 
 -- | Generate an infinite list of supplies by using 'supplyLeft' and
 -- 'supplyRight' repeatedly.
diff --git a/value-supply.cabal b/value-supply.cabal
--- a/value-supply.cabal
+++ b/value-supply.cabal
@@ -1,5 +1,5 @@
 Name:           value-supply
-Version:        0.2
+Version:        0.3
 License:        BSD3
 License-file:   LICENSE
 Author:         Iavor S. Diatchki
