diff --git a/Control/Monad/Crypto/Random.hs b/Control/Monad/Crypto/Random.hs
deleted file mode 100644
--- a/Control/Monad/Crypto/Random.hs
+++ /dev/null
@@ -1,195 +0,0 @@
-{-# LANGUAGE FlexibleInstances, TypeSynonymInstances, FlexibleContexts, GeneralizedNewtypeDeriving #-}
-{-|
-  Maintainer: Thomas.DuBuisson@gmail.com
-  Stability: beta
-  Portability: portable 
-
-Much like the "MonadRandom" package ("Control.Monad.Random"), this module
-provides plumbing for the CryptoRandomGen generators.
-
--}
- 
-module Control.Monad.Crypto.Random
-        ( CRandom(..)
-        , MonadCryptoRandom(..)
-        , CRandT
-        , CRand
-        , runCRandT
-        , evalCRandT
-        , runCRand
-        , evalCRand
-        ) where
-
-import Crypto.Random (CryptoRandomGen(..), GenError(..))
-import qualified Data.ByteString as B
-import Data.Bits (xor, setBit, shiftR, shiftL, (.&.))
-import Data.List (foldl')
-import Data.Word
-import Data.Int
-import Control.Arrow (right)
-import Control.Monad (liftM)
-import Control.Monad.Identity
-import Control.Monad.Error
-import Control.Monad.State
-
--- |@MonadCryptoRandom m@ represents a monad that can produce
--- random values (or fail with a 'GenError').  It is suggestd
--- you use the 'CRandT' transformer in your monad stack.
-class (MonadError GenError m) => MonadCryptoRandom m where
-        getCRandom   :: CRandom a => m a
-        getCRandomR  :: CRandom a => (a,a) -> m a
-        getBytes     :: Int -> m B.ByteString
-        getBytesWithEntropy :: Int -> B.ByteString -> m B.ByteString
-        doReseed :: B.ByteString -> m ()
-
--- |@CRandom a@ is much like the 'Random' class from the "System.Random" module in the "random" package.
--- The main difference is CRandom builds on "crypto-api"'s 'CryptoRandomGen', so it allows
--- explicit failure.
---
--- @crandomR (low,high) g@ as typically instantiated will generate a value between
--- [low, high] inclusively, swapping the pair if high < low.
---
--- Provided instances for @crandom g@ generates randoms between the bounds and between +/- 2^256
--- for Integer.
--- 
--- The 'crandomR' function has degraded (theoretically unbounded, probabilistically decent) performance
--- the closer your range size (high - low) is to 2^n (from the top).
-class CRandom a where
-    crandom   :: (CryptoRandomGen g) => g -> Either GenError (a, g)
-    crandomR  :: (CryptoRandomGen g) => (a, a) -> g -> Either GenError (a, g)
-    crandoms  :: (CryptoRandomGen g) => g -> [a]
-    crandoms g =
-        case crandom g of
-                Left _       -> []
-                Right (a,g') -> a : crandoms g'
-    crandomRs :: (CryptoRandomGen g) => (a, a) -> g -> [a]
-    crandomRs r g =
-        case crandomR r g of
-                Left _       -> []
-                Right (a,g') -> a : crandomRs r g'
-
-instance CRandom Integer where
-   crandom = crandomR ((-(2^256)), 2^256)
-   crandomR = crandomR_Num
-
-instance CRandom Int where
-    crandom = crandomR (minBound, maxBound)
-    crandomR = crandomR_Num
-
-instance CRandom Word8 where
-    crandom = crandomR (minBound, maxBound)
-    crandomR = crandomR_Num
-instance CRandom Word16 where
-    crandom = crandomR (minBound, maxBound)
-    crandomR = crandomR_Num
-instance CRandom Word32 where
-    crandom = crandomR (minBound, maxBound)
-    crandomR = crandomR_Num
-instance CRandom Word64 where
-    crandom = crandomR (minBound, maxBound)
-    crandomR = crandomR_Num
-
-instance CRandom Int8 where
-    crandom = crandomR (minBound, maxBound)
-    crandomR = crandomR_Num
-instance CRandom Int16 where
-    crandom = crandomR (minBound, maxBound)
-    crandomR = crandomR_Num
-instance CRandom Int32 where
-    crandom = crandomR (minBound, maxBound)
-    crandomR = crandomR_Num
-instance CRandom Int64 where
-    crandom = crandomR (minBound, maxBound)
-    crandomR = crandomR_Num
-
--- FIXME specialize
-crandomR_Num :: (Integral a, CryptoRandomGen g) => (a,a) -> g -> Either GenError (a,g)
-crandomR_Num (low, high) g
-      | high < low = crandomR_Num  (high,low) g
-      | high == low = Right (high, g)
-      | otherwise = go g
-      where
-      mask    = foldl' setBit 0 [0 .. fromIntegral nrBits - 1]
-      nrBits  = base2Log range
-      range :: Integer
-      range   = (fromIntegral high) - (fromIntegral low) + 1
-      nrBytes = (nrBits + 7) `div` 8
-      go gen =
-        let offset = genBytes (fromIntegral nrBytes) gen
-        in case offset of
-        Left err -> Left err
-        Right (bs, g') ->
-                let res = fromIntegral $ fromIntegral low + (bs2i bs .&. mask)
-                in if res > high then go g' else Right (res, g')
-
-wrap :: (Monad m) => (g -> Either GenError (a,g)) -> CRandT g m a
-wrap f = CRandT $ do
-        g <- get
-        case f g of
-                Right (a,g') -> put g' >> return a
-                Left x -> throwError x
-
--- |CRandT is the transformer suggested for MonadCryptoRandom.
-newtype CRandT g m a = CRandT { unCRandT :: StateT g (ErrorT GenError m) a } deriving (MonadError GenError, Monad)
-
-instance MonadTrans (CRandT g) where
-	lift = CRandT . lift . lift
-
--- |Simple users of generators can use CRand for
--- quick and easy generation of randoms.  See
--- below for a simple use of 'newGenIO' (from "crypto-api"),
--- 'getCRandom', 'getBytes', and 'runCRandom'.
---
--- @getRandPair = do
---   int <- getCRandom
---   bytes <- getBytes 100
---   return (int, bytes)
---
---  func = do
---   g <- newGenIO
---   case runCRand getRandPair g of
---       Right ((int,bytes), g') -> useRandomVals (int,bytes)
---       Left x -> handleGenError x
--- @
-type CRand g = CRandT g Identity
-
-runCRandT :: CRandT g m a -> g -> m (Either GenError (a,g))
-runCRandT m g = runErrorT . flip runStateT g . unCRandT $ m
-
-evalCRandT :: Monad m => CRandT g m a -> g -> m (Either GenError a)
-evalCRandT m g = liftM (right fst) (runCRandT m g)
-
-runCRand :: CRand g a -> g -> Either GenError (a, g)
-runCRand m = runIdentity . runCRandT m
-
-evalCRand :: CRand g a -> g -> Either GenError a
-evalCRand m = runIdentity . evalCRandT m
-
-instance (Monad m, CryptoRandomGen g) => MonadCryptoRandom (CRandT g m) where
-        getCRandom  = wrap crandom
-        getCRandomR = wrap . crandomR
-        getBytes i = wrap (genBytes i)
-        getBytesWithEntropy i e = wrap (genBytesWithEntropy i e)
-        doReseed bs = CRandT $ do
-                        get >>= \g ->
-                         case reseed bs g of
-                            Right g' -> put g'
-                            Left  x  -> throwError x
-
-instance Error GenError where
-        noMsg = GenErrorOther "noMsg"
-        strMsg = GenErrorOther
-
-base2Log :: Integer -> Integer
-base2Log i
-        | i >= setBit 0 64 = 64 + base2Log (i `shiftR` 64)
-        | i >= setBit 0 32 = 32 + base2Log (i `shiftR` 32)
-        | i >= setBit 0 16 = 16 + base2Log (i `shiftR` 16)
-        | i >= setBit 0 8  = 8  + base2Log (i `shiftR` 8)
-        | i >= setBit 0 0  = 1  + base2Log (i `shiftR` 1)
-        | otherwise        = 0
-
-bs2i :: B.ByteString -> Integer
-bs2i bs = B.foldl' (\i b -> (i `shiftL` 8) + fromIntegral b) 0 bs
-{-# INLINE bs2i #-}
-
diff --git a/Control/Monad/CryptoRandom.hs b/Control/Monad/CryptoRandom.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/CryptoRandom.hs
@@ -0,0 +1,205 @@
+{-# LANGUAGE FlexibleInstances, TypeSynonymInstances, FlexibleContexts, GeneralizedNewtypeDeriving, MultiParamTypeClasses #-}
+{-|
+  Maintainer: Thomas.DuBuisson@gmail.com
+  Stability: beta
+  Portability: portable 
+
+Much like the "MonadRandom" package ("Control.Monad.Random"), this module
+provides plumbing for the CryptoRandomGen generators.
+
+-}
+ 
+module Control.Monad.CryptoRandom
+        ( CRandom(..)
+        , MonadCryptoRandom(..)
+	, ContainsGenError(..)
+        , CRandT
+        , CRand
+        , runCRandT
+        , evalCRandT
+        , runCRand
+        , evalCRand
+        ) where
+
+import Crypto.Random (CryptoRandomGen(..), GenError(..))
+import qualified Data.ByteString as B
+import Data.Bits (xor, setBit, shiftR, shiftL, (.&.))
+import Data.List (foldl')
+import Data.Word
+import Data.Int
+import Control.Arrow (right, left)
+import Control.Monad (liftM)
+import Control.Monad.Identity
+import Control.Monad.Error
+import Control.Monad.State
+import Control.Monad.IO.Class
+
+-- |@MonadCryptoRandom m@ represents a monad that can produce
+-- random values (or fail with a 'GenError').  It is suggestd
+-- you use the 'CRandT' transformer in your monad stack.
+class (ContainsGenError e, MonadError e m) => MonadCryptoRandom e m where
+        getCRandom   :: CRandom a => m a
+        getCRandomR  :: CRandom a => (a,a) -> m a
+        getBytes     :: Int -> m B.ByteString
+        getBytesWithEntropy :: Int -> B.ByteString -> m B.ByteString
+        doReseed :: B.ByteString -> m ()
+
+class ContainsGenError e where
+	toGenError :: e -> Maybe GenError
+	fromGenError :: GenError -> e
+
+instance ContainsGenError GenError where
+	toGenError = Just
+	fromGenError = id
+
+-- |@CRandom a@ is much like the 'Random' class from the "System.Random" module in the "random" package.
+-- The main difference is CRandom builds on "crypto-api"'s 'CryptoRandomGen', so it allows
+-- explicit failure.
+--
+-- @crandomR (low,high) g@ as typically instantiated will generate a value between
+-- [low, high] inclusively, swapping the pair if high < low.
+--
+-- Provided instances for @crandom g@ generates randoms between the bounds and between +/- 2^256
+-- for Integer.
+-- 
+-- The 'crandomR' function has degraded (theoretically unbounded, probabilistically decent) performance
+-- the closer your range size (high - low) is to 2^n (from the top).
+class CRandom a where
+    crandom   :: (CryptoRandomGen g) => g -> Either GenError (a, g)
+    crandomR  :: (CryptoRandomGen g) => (a, a) -> g -> Either GenError (a, g)
+    crandoms  :: (CryptoRandomGen g) => g -> [a]
+    crandoms g =
+        case crandom g of
+                Left _       -> []
+                Right (a,g') -> a : crandoms g'
+    crandomRs :: (CryptoRandomGen g) => (a, a) -> g -> [a]
+    crandomRs r g =
+        case crandomR r g of
+                Left _       -> []
+                Right (a,g') -> a : crandomRs r g'
+
+instance CRandom Integer where
+   crandom = crandomR ((-(2^256)), 2^256)
+   crandomR = crandomR_Num
+
+instance CRandom Int where
+    crandom = crandomR (minBound, maxBound)
+    crandomR = crandomR_Num
+
+instance CRandom Word8 where
+    crandom = crandomR (minBound, maxBound)
+    crandomR = crandomR_Num
+instance CRandom Word16 where
+    crandom = crandomR (minBound, maxBound)
+    crandomR = crandomR_Num
+instance CRandom Word32 where
+    crandom = crandomR (minBound, maxBound)
+    crandomR = crandomR_Num
+instance CRandom Word64 where
+    crandom = crandomR (minBound, maxBound)
+    crandomR = crandomR_Num
+
+instance CRandom Int8 where
+    crandom = crandomR (minBound, maxBound)
+    crandomR = crandomR_Num
+instance CRandom Int16 where
+    crandom = crandomR (minBound, maxBound)
+    crandomR = crandomR_Num
+instance CRandom Int32 where
+    crandom = crandomR (minBound, maxBound)
+    crandomR = crandomR_Num
+instance CRandom Int64 where
+    crandom = crandomR (minBound, maxBound)
+    crandomR = crandomR_Num
+
+-- FIXME specialize
+crandomR_Num :: (Integral a, CryptoRandomGen g) => (a,a) -> g -> Either GenError (a,g)
+crandomR_Num (low, high) g
+      | high < low = crandomR_Num  (high,low) g
+      | high == low = Right (high, g)
+      | otherwise = go g
+      where
+      mask    = foldl' setBit 0 [0 .. fromIntegral nrBits - 1]
+      nrBits  = base2Log range
+      range :: Integer
+      range   = (fromIntegral high) - (fromIntegral low) + 1
+      nrBytes = (nrBits + 7) `div` 8
+      go gen =
+        let offset = genBytes (fromIntegral nrBytes) gen
+        in case offset of
+        Left err -> Left err
+        Right (bs, g') ->
+                let res = fromIntegral $ fromIntegral low + (bs2i bs .&. mask)
+                in if res > high then go g' else Right (res, g')
+
+wrap :: (Monad m, ContainsGenError e, Error e) => (g -> Either GenError (a,g)) -> CRandT g e m a
+wrap f = CRandT $ do
+        g <- get
+        case f g of
+                Right (a,g') -> put g' >> return a
+                Left x -> throwError (fromGenError x)
+
+-- |CRandT is the transformer suggested for MonadCryptoRandom.
+newtype CRandT g e m a = CRandT { unCRandT :: StateT g (ErrorT e m) a } deriving (MonadError e, Monad, MonadIO)
+
+instance (Error e) => MonadTrans (CRandT g e) where
+	lift = CRandT . lift . lift
+
+-- |Simple users of generators can use CRand for
+-- quick and easy generation of randoms.  See
+-- below for a simple use of 'newGenIO' (from "crypto-api"),
+-- 'getCRandom', 'getBytes', and 'runCRandom'.
+--
+-- @getRandPair = do
+--   int <- getCRandom
+--   bytes <- getBytes 100
+--   return (int, bytes)
+--
+--  func = do
+--   g <- newGenIO
+--   case runCRand getRandPair g of
+--       Right ((int,bytes), g') -> useRandomVals (int,bytes)
+--       Left x -> handleGenError x
+-- @
+type CRand g e = CRandT g e Identity
+
+runCRandT :: ContainsGenError e => CRandT g e m a -> g -> m (Either e (a,g))
+runCRandT m g = runErrorT . flip runStateT g . unCRandT $ m
+
+evalCRandT :: (ContainsGenError e, Monad m) => CRandT g e m a -> g -> m (Either e a)
+evalCRandT m g = liftM (right fst) (runCRandT m g)
+
+runCRand :: CRand g GenError a -> g -> Either GenError (a, g)
+runCRand m = runIdentity . runCRandT m
+
+evalCRand :: CRand g GenError a -> g -> Either GenError a
+evalCRand m = runIdentity . evalCRandT m
+
+instance (ContainsGenError e, Error e, Monad m, CryptoRandomGen g) => MonadCryptoRandom e (CRandT g e m) where
+        getCRandom  = wrap crandom
+        getCRandomR = wrap . crandomR
+        getBytes i = wrap (genBytes i)
+        getBytesWithEntropy i e = wrap (genBytesWithEntropy i e)
+        doReseed bs = CRandT $ do
+                        get >>= \g ->
+                         case reseed bs g of
+                            Right g' -> put g'
+                            Left  x  -> throwError (fromGenError x)
+
+instance Error GenError where
+        noMsg = GenErrorOther "noMsg"
+        strMsg = GenErrorOther
+
+base2Log :: Integer -> Integer
+base2Log i
+        | i >= setBit 0 64 = 64 + base2Log (i `shiftR` 64)
+        | i >= setBit 0 32 = 32 + base2Log (i `shiftR` 32)
+        | i >= setBit 0 16 = 16 + base2Log (i `shiftR` 16)
+        | i >= setBit 0 8  = 8  + base2Log (i `shiftR` 8)
+        | i >= setBit 0 0  = 1  + base2Log (i `shiftR` 1)
+        | otherwise        = 0
+
+bs2i :: B.ByteString -> Integer
+bs2i bs = B.foldl' (\i b -> (i `shiftL` 8) + fromIntegral b) 0 bs
+{-# INLINE bs2i #-}
+
diff --git a/monadcryptorandom.cabal b/monadcryptorandom.cabal
--- a/monadcryptorandom.cabal
+++ b/monadcryptorandom.cabal
@@ -1,5 +1,5 @@
 name:           monadcryptorandom
-version:        0.2
+version:        0.3
 license:        BSD3
 license-file:   LICENSE
 copyright:      Thomas DuBuisson <thomas.dubuisson@gmail.com>
@@ -20,7 +20,7 @@
 Library
   Build-Depends: base == 4.*,
                  bytestring >= 0.9 && < 0.10,
-                 mtl >= 2.0, crypto-api >= 0.2
+                 mtl >= 2.0, crypto-api >= 0.2, transformers >= 0.2
   ghc-options:
   hs-source-dirs:
-  exposed-modules: Control.Monad.Crypto.Random
+  exposed-modules: Control.Monad.CryptoRandom
