diff --git a/random-fu.cabal b/random-fu.cabal
--- a/random-fu.cabal
+++ b/random-fu.cabal
@@ -1,5 +1,5 @@
 name:                   random-fu
-version:                0.1.4
+version:                0.2
 stability:              provisional
 
 cabal-version:          >= 1.6
@@ -29,33 +29,18 @@
                         a fair bit slower than straight C implementations of 
                         the same algorithms.
                         
-                        Warning to anyone upgrading from \"< 0.1\": 'Discrete'
-                        has been renamed 'Categorical', the entropy source 
-                        classes have been redesigned, and many things are no
-                        longer exported from the root module "Data.Random"
-                        (In particular, DevRandom - this is not available on 
-                        windows, so it will likely move to its own package 
-                        eventually so that client code dependencies on it will 
-                        be made explicit).
-                        
-                        Support for "base" packages earlier than version 4
-                        (and thus GHC releases earlier than 6.10) has been 
-                        dropped, as too many of this package's dependencies do
-                        not support older versions.
+                        Warning to anyone upgrading from \"< 0.2\": The old
+                        random-fu package has been split into three parts: 
+                        random-source, rvar, and this new random-fu.  The
+                        end-user interface is mostly the same.
                         
-                        The "Data.Random" module itself should now have a
-                        relatively stable interface, but the other modules
-                        are still subject to change.  Specifically, I am 
-                        considering hiding data constructors for most or all 
-                        of the distributions.
-
-Tested-with:            GHC == 6.10.4, GHC == 6.12.1, GHC == 6.12.3,
+tested-with:            GHC == 6.10.4, GHC == 6.12.1, GHC == 6.12.3,
                         GHC == 7.0.1, GHC == 7.0.2
 
 source-repository head
   type:                 git
   location:             https://github.com/mokus0/random-fu.git
-  branch:               v0.1-series
+  subdir:               random-fu
 
 Flag base4_2
     Description:        base-4.2 has an incompatible change in Data.Fixed (HasResolution)
@@ -72,6 +57,7 @@
                         Data.Random.Distribution.Beta
                         Data.Random.Distribution.Binomial
                         Data.Random.Distribution.Categorical
+                        Data.Random.Distribution.ChiSquare
                         Data.Random.Distribution.Dirichlet
                         Data.Random.Distribution.Exponential
                         Data.Random.Distribution.Gamma
@@ -85,18 +71,11 @@
                         Data.Random.Distribution.Ziggurat
                         Data.Random.Internal.Find
                         Data.Random.Internal.Fixed
-                        Data.Random.Internal.Primitives
                         Data.Random.Internal.TH
-                        Data.Random.Internal.Words
                         Data.Random.Lift
                         Data.Random.List
                         Data.Random.RVar
                         Data.Random.Sample
-                        Data.Random.Source
-                        Data.Random.Source.MWC
-                        Data.Random.Source.PureMT
-                        Data.Random.Source.Std
-                        Data.Random.Source.StdGen
   if flag(base4_2)
     build-depends:      base >= 4.2 && <5
   else
@@ -109,23 +88,18 @@
   else
     build-depends:      mtl == 1.*
   
-  build-depends:        array,
-                        containers,
-                        mersenne-random-pure64,
+  build-depends:        gamma,
                         monad-loops >= 0.3.0.1,
-                        MonadPrompt,
-                        mwc-random,
-                        random,
                         random-shuffle,
-                        stateref >= 0.3 && < 0.4,
+                        random-source == 0.3.*,
+                        rvar == 0.2.*,
                         syb,
-                        tagged,
                         template-haskell,
-                        vector
-  
+                        transformers,
+                        vector >= 0.7
+
   if os(Windows)
     cpp-options:        -Dwindows
     build-depends:      erf-native
   else
     build-depends:      erf
-    exposed-modules:    Data.Random.Source.DevRandom
diff --git a/src/Data/Random.hs b/src/Data/Random.hs
--- a/src/Data/Random.hs
+++ b/src/Data/Random.hs
@@ -64,6 +64,7 @@
 
 import Data.Random.Sample
 import Data.Random.Source (MonadRandom, RandomSource)
+import Data.Random.Source.IO ()
 import Data.Random.Source.MWC ()
 import Data.Random.Source.StdGen ()
 import Data.Random.Source.PureMT ()
diff --git a/src/Data/Random/Distribution/Bernoulli.hs b/src/Data/Random/Distribution/Bernoulli.hs
--- a/src/Data/Random/Distribution/Bernoulli.hs
+++ b/src/Data/Random/Distribution/Bernoulli.hs
@@ -1,6 +1,3 @@
-{-
- -      ``Data/Random/Distribution/Bernoulli''
- -}
 {-# LANGUAGE
     MultiParamTypeClasses,
     FlexibleInstances, FlexibleContexts,
diff --git a/src/Data/Random/Distribution/Beta.hs b/src/Data/Random/Distribution/Beta.hs
--- a/src/Data/Random/Distribution/Beta.hs
+++ b/src/Data/Random/Distribution/Beta.hs
@@ -1,6 +1,3 @@
-{-
- -      ``Data/Random/Distribution/Beta''
- -}
 {-# LANGUAGE
     MultiParamTypeClasses,
     FlexibleInstances, FlexibleContexts,
diff --git a/src/Data/Random/Distribution/Binomial.hs b/src/Data/Random/Distribution/Binomial.hs
--- a/src/Data/Random/Distribution/Binomial.hs
+++ b/src/Data/Random/Distribution/Binomial.hs
@@ -1,6 +1,3 @@
-{-
- -      ``Data/Random/Distribution/Binomial''
- -}
 {-# LANGUAGE
     MultiParamTypeClasses,
     FlexibleInstances, FlexibleContexts,
diff --git a/src/Data/Random/Distribution/Categorical.hs b/src/Data/Random/Distribution/Categorical.hs
--- a/src/Data/Random/Distribution/Categorical.hs
+++ b/src/Data/Random/Distribution/Categorical.hs
@@ -1,12 +1,15 @@
-{-
- -      ``Data/Random/Distribution/Categorical''
- -}
 {-# LANGUAGE
     MultiParamTypeClasses,
     FlexibleInstances, FlexibleContexts
   #-}
 
-module Data.Random.Distribution.Categorical where
+module Data.Random.Distribution.Categorical
+    ( categorical, categoricalT
+    , fromList, toList
+    , fromWeightedList, fromObservations
+    , mapCategoricalPs, normalizeCategoricalPs
+    , collectEvents, collectEventsBy
+    ) where
 
 import Data.Random.RVar
 import Data.Random.Distribution
@@ -14,91 +17,108 @@
 
 import Control.Arrow
 import Control.Monad
+import Control.Monad.ST
 import Control.Applicative
 import Data.Foldable (Foldable(foldMap))
+import Data.STRef
 import Data.Traversable (Traversable(traverse, sequenceA))
 
 import Data.List
 import Data.Function
+import qualified Data.Vector as V
+import qualified Data.Vector.Mutable as MV
 
 -- |Construct a 'Categorical' random variable from a list of probabilities
 -- and categories, where the probabilities all sum to 1.
-categorical :: Distribution (Categorical p) a => [(p,a)] -> RVar a
-categorical ps = rvar (Categorical ps)
+categorical :: (Num p, Distribution (Categorical p) a) => [(p,a)] -> RVar a
+categorical = rvar . fromList
 
--- |Construct a 'Categorical' random process from a list of probabilities
+-- |Construct a 'Categorical' random process from a list of probabilities 
 -- and categories, where the probabilities all sum to 1.
-categoricalT :: Distribution (Categorical p) a => [(p,a)] -> RVarT m a
-categoricalT ps = rvarT (Categorical ps)
+categoricalT :: (Num p, Distribution (Categorical p) a) => [(p,a)] -> RVarT m a
+categoricalT = rvarT . fromList
 
--- | Construct a 'Categorical' distribution from a list of weighted categories,
+-- | Construct a 'Categorical' distribution from a list of weighted categories.
+{-# INLINE fromList #-}
+fromList :: (Num p) => [(p,a)] -> Categorical p a
+fromList xs = Categorical (V.fromList (scanl1 f xs))
+    where f (p0, _) (p1, y) = (p0 + p1, y)
+
+{-# INLINE toList #-}
+toList :: (Num p) => Categorical p a -> [(p,a)]
+toList (Categorical ds) = V.foldr' g [] ds
+    where
+        g x [] = [x]
+        g x@(p0,_) ((p1, y):xs) = x : (p1-p0,y) : xs
+
+-- |Construct a 'Categorical' distribution from a list of weighted categories, 
 -- where the weights do not necessarily sum to 1.
-{-# INLINE weightedCategorical #-}
-weightedCategorical :: (Fractional p) => [(p,a)] -> Categorical p a
-weightedCategorical = normalizeCategoricalPs . Categorical
+fromWeightedList :: (Fractional p, Ord a) => [(p,a)] -> Categorical p a
+fromWeightedList = normalizeCategoricalPs . fromList
 
 -- |Construct a 'Categorical' distribution from a list of observed outcomes.
 -- Equivalent events will be grouped and counted, and the probabilities of each
 -- event in the returned distribution will be proportional to the number of 
 -- occurrences of that event.
-empirical :: (Fractional p, Ord a) => [a] -> Categorical p a
-empirical xs = normalizeCategoricalPs (Categorical bins)
-    where bins = [ (genericLength bin, x)
-                 | bin@(x:_) <- group (sort xs)
-                 ]
+fromObservations :: (Fractional p, Ord a) => [a] -> Categorical p a
+fromObservations = fromWeightedList . map (genericLength &&& head) . group . sort
 
 -- |Categorical distribution; a list of events with corresponding probabilities.
 -- The sum of the probabilities must be 1, and no event should have a zero 
 -- or negative probability (at least, at time of sampling; very clever users
 -- can do what they want with the numbers before sampling, just make sure 
 -- that if you're one of those clever ones, you normalize before sampling).
-newtype Categorical p a = Categorical [(p, a)]
-    deriving (Eq, Show)
+newtype Categorical p a = Categorical (V.Vector (p, a))
+    deriving Eq
 
-instance (Fractional p, Ord p, Distribution StdUniform p) => Distribution (Categorical p) a where
-    rvarT (Categorical []) = fail "categorical distribution over empty set cannot be sampled"
-    rvarT (Categorical ds) = do
-        let (ps, xs) = unzip ds
-            cs = scanl1 (+) ps
-        
-        u <- stdUniformT
-        getEvent u cs xs
-        
-        where
-            -- In the (hopefully) extremely rare event that, due to numerical
-            -- instability, the last 'c' is less than 1 _and_ a number greater than 
-            -- it is drawn, simply retry the sampling.  If it comes to that, also
-            -- do one last sanity check that lastC > 0, to make sure that there
-            -- is some nonzero chance of termination.
-            getEvent u cs0 xs0 = go 0 cs0 xs0
-                where
-                    go lastC [] _
-                        | lastC > 0 = do {newU <- stdUniformT; getEvent newU cs0 xs0}
-                        | otherwise = fail "categorical distribution sampling error: total probablility not greater than zero"
-                    go lastC (c:cs) (x:xs)
-                        | c < lastC = fail "categorical distribution sampling error: negative probability for an event!"
-                        | u > c     = go c cs xs
-                        | c == c    = return x
-                        | otherwise = fail "categorical distribution sampling error: NaN probability"
-                    
-                    go _ _ _ = error "rvar/Categorical: programming error! this case should be impossible!"
+instance (Num p, Show a) => Show (Categorical p a) where
+    showsPrec p cat = showParen (p>10)
+        ( showString "fromList "
+        . showsPrec 11 (toList cat)
+        )
 
+instance (Fractional p, Ord p, Distribution Uniform p) => Distribution (Categorical p) a where
+    rvarT (Categorical ds)
+        | V.null ds = fail "categorical distribution over empty set cannot be sampled"
+        | n == 1    = return (snd (V.head ds))
+        | otherwise = do
+            u <- uniformT 0 (fst (V.last ds))
+            
+            let p i = fst (ds V.! i)
+                x i = snd (ds V.! i)
+                
+                -- find the smallest entry whose cumulative probability is
+                -- greater than or equal to u
+                -- invariant: p j >= u
+                -- variant: at every step, either i increases or j decreases.
+                findEvent i j
+                    | i >= j    = x j
+                    | p m >= u  = findEvent i m
+                    | otherwise = findEvent (max m (i+1)) j
+                    where
+                        -- midpoint rounding down
+                        m = (i + j) `div` 2
+            
+            return (findEvent 0 (n-1))
+        where n = V.length ds
+
+
 instance Functor (Categorical p) where
-    fmap f (Categorical ds) = Categorical [(p, f x) | ~(p, x) <- ds]
+    fmap f (Categorical ds) = Categorical (V.map (second f) ds)
 
 instance Foldable (Categorical p) where
-    foldMap f (Categorical ds) = foldMap (f . snd) ds
+    foldMap f (Categorical ds) = foldMap (f . snd) (V.toList ds)
 
 instance Traversable (Categorical p) where
-    traverse f (Categorical ds) = Categorical <$> traverse (\(p,e) -> (\e' -> (p,e')) <$> f e) ds
-    sequenceA  (Categorical ds) = Categorical <$> traverse (\(p,e) -> (\e' -> (p,e')) <$>   e) ds
+    traverse f (Categorical ds) = Categorical . V.fromList <$> traverse (\(p,e) -> (\e' -> (p,e')) <$> f e) (V.toList ds)
+    sequenceA  (Categorical ds) = Categorical . V.fromList <$> traverse (\(p,e) -> (\e' -> (p,e')) <$>   e) (V.toList ds)
 
-instance Fractional p => Monad (Categorical p) where
-    return x = Categorical [(1, x)]
+instance Num p => Monad (Categorical p) where
+    return x = Categorical (V.singleton (1, x))
     
     -- I'm not entirely sure whether this is a valid form of failure; see next
     -- set of comments.
-    fail _ = Categorical []
+    fail _ = Categorical V.empty
     
     -- Should the normalize step be included here, or should normalization
     -- be assumed?  It seems like there is (at least) 1 valid situation where
@@ -114,11 +134,9 @@
     -- user (who really better know what they mean if they're returning
     -- non-normalized probability anyway) to normalize explicitly than to
     -- undo any normalization that was done automatically.
-    (Categorical xs) >>= f = {- normalizeCategoricalPs . -} Categorical $ do
-        (p, x) <- xs
-        
-        let Categorical fx = f x
-        (q, y) <- fx
+    xs >>= f = {- normalizeCategoricalPs . -} fromList $ do
+        (p, x) <- toList xs
+        (q, y) <- toList (f x)
         
         return (p * q, y)
 
@@ -128,32 +146,50 @@
 
 -- |Like 'fmap', but for the probabilities of a categorical distribution.
 mapCategoricalPs :: (p -> q) -> Categorical p e -> Categorical q e
-mapCategoricalPs f (Categorical ds) = Categorical [(f p, x) | (p, x) <- ds]
+mapCategoricalPs f (Categorical ds) = Categorical (V.map (first f) ds)
 
 -- |Adjust all the weights of a categorical distribution so that they 
 -- sum to unity.
 normalizeCategoricalPs :: (Fractional p) => Categorical p e -> Categorical p e
 normalizeCategoricalPs orig@(Categorical ds) = 
-    -- For practical purposes the scale factor is strict anyway,
-    -- so check if the total probability is 1 and, if so, skip 
-    -- the actual scaling part.
-    --
-    -- Along the way, discard any zero-probability events.
-    if null ds || ps =~ 1
+    if V.null ds
         then orig
-        else Categorical
-                [ (p * scale, e)
-                | (p, e) <- ds
-                , p /= 0
-                ] 
+        else runST $ do
+            let n = V.length ds
+            lastP       <- newSTRef 0
+            dups        <- newSTRef 0
+            normalized  <- V.thaw ds
+            
+            let skip = modifySTRef' dups (1+)
+                save i p x = do
+                    d <- readSTRef dups
+                    MV.write normalized (i-d) (p, x)
+            
+            sequence_
+                [ do
+                    let (p,x) = ds V.! i
+                    p0 <- readSTRef lastP
+                    if p == p0
+                        then skip
+                        else do
+                            save i (p * scale) x
+                            writeSTRef lastP p
+                | i <- [0..n-1]
+                ]
+            
+            -- force last element to 1
+            d <- readSTRef dups
+            MV.write normalized (n-d-1) (1,lastX)
+            Categorical <$> V.unsafeFreeze (MV.unsafeSlice 0 (n-d) normalized)
     where
-        ps = foldl1' (+) (map fst ds)
+        (ps, lastX) = V.last ds
         scale = recip ps
-        
-        -- Using same implicit-epsilon trick as in Distribution instance
-        -- (see comments there)
-        x =~ y  = (100 + (x-y) == 100)
 
+modifySTRef' :: STRef s a -> (a -> a) -> ST s ()
+modifySTRef' x f = do
+    v <- readSTRef x
+    let fv = f v
+    fv `seq` writeSTRef x fv
 
 -- |Simplify a categorical distribution by combining equivalent categories (the new
 -- category will have a probability equal to the sum of all the originals).
@@ -165,9 +201,9 @@
 -- The comparator function is used to identify events to combine.  Once chosen,
 -- the events and their weights are combined by the provided probability and
 -- event aggregation function.
-collectEventsBy :: (e -> e -> Ordering) -> ([(p,e)] -> (p,e))-> Categorical p e -> Categorical p e
-collectEventsBy compareE combine (Categorical ds) = 
-    Categorical . map combine . groupEvents . sortEvents $ ds
+collectEventsBy :: Num p => (e -> e -> Ordering) -> ([(p,e)] -> (p,e))-> Categorical p e -> Categorical p e
+collectEventsBy compareE combine = 
+    fromList . map combine . groupEvents . sortEvents . toList
     where
         groupEvents = groupBy (\x y -> snd x `compareE` snd y == EQ)
         sortEvents  = sortBy (compareE `on` snd)
diff --git a/src/Data/Random/Distribution/ChiSquare.hs b/src/Data/Random/Distribution/ChiSquare.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Random/Distribution/ChiSquare.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE
+        MultiParamTypeClasses, FlexibleInstances, FlexibleContexts,
+        UndecidableInstances
+  #-}
+module Data.Random.Distribution.ChiSquare where
+
+import Data.Random.RVar
+import Data.Random.Distribution
+import Data.Random.Distribution.Gamma
+
+import Math.Gamma (p)
+
+chiSquare :: Distribution ChiSquare t => Integer -> RVar t
+chiSquare = rvar . ChiSquare
+
+chiSquareT :: Distribution ChiSquare t => Integer -> RVarT m t
+chiSquareT = rvarT . ChiSquare
+
+newtype ChiSquare b = ChiSquare Integer
+
+instance (Fractional t, Distribution Gamma t) => Distribution ChiSquare t where
+    rvarT (ChiSquare 0) = return 0
+    rvarT (ChiSquare n)
+        | n > 0     = gammaT (0.5 * fromInteger n) 2
+        | otherwise = fail "chi-square distribution: degrees of freedom must be positive"
+
+instance (Real t, Distribution ChiSquare t) => CDF ChiSquare t where
+    cdf (ChiSquare n) x = p (0.5 * fromInteger n) (0.5 * realToFrac x)
diff --git a/src/Data/Random/Distribution/Exponential.hs b/src/Data/Random/Distribution/Exponential.hs
--- a/src/Data/Random/Distribution/Exponential.hs
+++ b/src/Data/Random/Distribution/Exponential.hs
@@ -1,6 +1,3 @@
-{-
- -      ``Data/Random/Distribution/Exponential''
- -}
 {-# LANGUAGE
     MultiParamTypeClasses,
     FlexibleInstances, FlexibleContexts,
diff --git a/src/Data/Random/Distribution/Gamma.hs b/src/Data/Random/Distribution/Gamma.hs
--- a/src/Data/Random/Distribution/Gamma.hs
+++ b/src/Data/Random/Distribution/Gamma.hs
@@ -21,6 +21,8 @@
 
 import Data.Ratio
 
+import Math.Gamma (p)
+
 -- |derived from  Marsaglia & Tang, "A Simple Method for generating gamma
 -- variables", ACM Transactions on Mathematical Software, Vol 26, No 3 (2000), p363-372.
 {-# SPECIALIZE mtGamma :: Double -> Double -> RVarT m Double #-}
@@ -77,5 +79,12 @@
     {-# SPECIALIZE instance Distribution Gamma Float #-}
     rvarT (Gamma a b) = mtGamma a b
 
+instance (Real a, Distribution Gamma a) => CDF Gamma a where
+    cdf (Gamma a b) x = p (realToFrac a) (realToFrac x / realToFrac b)
+
 instance (Integral a, Floating b, Ord b, Distribution Normal b, Distribution StdUniform b) => Distribution (Erlang a) b where
     rvarT (Erlang a) = mtGamma (fromIntegral a) 1
+
+instance (Integral a, Real b, Distribution (Erlang a) b) => CDF (Erlang a) b where
+    cdf (Erlang a) x = p (fromIntegral a) (realToFrac x)
+
diff --git a/src/Data/Random/Distribution/Normal.hs b/src/Data/Random/Distribution/Normal.hs
--- a/src/Data/Random/Distribution/Normal.hs
+++ b/src/Data/Random/Distribution/Normal.hs
@@ -138,7 +138,7 @@
         
         getIU :: (Num a, Distribution Uniform a) => RVarT m (Int, a)
         getIU = do
-            i <- getRandomPrim PrimWord8
+            i <- getRandomWord8
             u <- uniformT (-1) 1
             return (fromIntegral i .&. (2^p-1), u)
 
@@ -164,7 +164,7 @@
     where 
         getIU :: RVarT m (Int, Double)
         getIU = do
-            !w <- getRandomPrim PrimWord64
+            !w <- getRandomWord64
             let (u,i) = wordToDoubleWithExcess w
             return $! (fromIntegral i .&. (doubleStdNormalC-1), u+u-1)
 
@@ -190,7 +190,7 @@
     where
         getIU :: RVarT m (Int, Float)
         getIU = do
-            !w <- getRandomPrim PrimWord32
+            !w <- getRandomWord32
             let (u,i) = word32ToFloatWithExcess w
             return (fromIntegral i .&. (floatStdNormalC-1), u+u-1)
 
diff --git a/src/Data/Random/Distribution/Poisson.hs b/src/Data/Random/Distribution/Poisson.hs
--- a/src/Data/Random/Distribution/Poisson.hs
+++ b/src/Data/Random/Distribution/Poisson.hs
@@ -1,6 +1,3 @@
-{-
- -      ``Data/Random/Distribution/Poisson''
- -}
 {-# LANGUAGE
     MultiParamTypeClasses,
     FlexibleInstances, FlexibleContexts, UndecidableInstances,
diff --git a/src/Data/Random/Distribution/Rayleigh.hs b/src/Data/Random/Distribution/Rayleigh.hs
--- a/src/Data/Random/Distribution/Rayleigh.hs
+++ b/src/Data/Random/Distribution/Rayleigh.hs
@@ -1,6 +1,3 @@
-{-
- -      ``Data/Random/Distribution/Rayleigh''
- -}
 {-# LANGUAGE
         MultiParamTypeClasses, 
         FlexibleInstances, FlexibleContexts,
diff --git a/src/Data/Random/Distribution/Triangular.hs b/src/Data/Random/Distribution/Triangular.hs
--- a/src/Data/Random/Distribution/Triangular.hs
+++ b/src/Data/Random/Distribution/Triangular.hs
@@ -1,6 +1,3 @@
-{-
- -      ``Data/Random/Distribution/Triangular''
- -}
 {-# LANGUAGE
     MultiParamTypeClasses,
     FlexibleInstances, FlexibleContexts,
diff --git a/src/Data/Random/Distribution/Uniform.hs b/src/Data/Random/Distribution/Uniform.hs
--- a/src/Data/Random/Distribution/Uniform.hs
+++ b/src/Data/Random/Distribution/Uniform.hs
@@ -1,6 +1,3 @@
-{-
- -      ``Data/Random/Distribution/Uniform''
- -}
 {-# LANGUAGE
     MultiParamTypeClasses, FunctionalDependencies,
     FlexibleContexts, FlexibleInstances, 
@@ -48,7 +45,6 @@
 import Data.Fixed
 import Data.Word
 import Data.Int
-import Data.List
 
 import Control.Monad.Loops
 
@@ -77,7 +73,7 @@
         (bytes, nPossible) = bytesNeeded m
         nReject = nPossible `mod` m
         
-        !prim = getRandomPrim (PrimNByteInteger bytes)
+        !prim = getRandomNByteInteger bytes
         !shift = \(!z) -> l + (fromInteger $! (z `mod` m))
         
         loop = do
@@ -121,13 +117,13 @@
 -- |Compute a uniform random 'Float' value in the range [0,1)
 floatStdUniform :: RVarT m Float
 floatStdUniform = do
-    x <- getRandomPrim PrimWord32
+    x <- getRandomWord32
     return (word32ToFloat x)
 
 -- |Compute a uniform random 'Double' value in the range [0,1)
 {-# INLINE doubleStdUniform #-}
 doubleStdUniform :: RVarT m Double
-doubleStdUniform = getRandomPrim PrimDouble
+doubleStdUniform = getRandomDouble
 
 -- |Compute a uniform random value in the range [0,1) for any 'RealFloat' type 
 realFloatStdUniform :: RealFloat a => RVarT m a
@@ -283,27 +279,27 @@
         instance CDF Uniform Int            where cdf   (Uniform a b) = integralUniformCDF a b
     |])
 
-instance Distribution StdUniform Word8      where rvarT ~StdUniform = getRandomPrim PrimWord8
-instance Distribution StdUniform Word16     where rvarT ~StdUniform = getRandomPrim PrimWord16
-instance Distribution StdUniform Word32     where rvarT ~StdUniform = getRandomPrim PrimWord32
-instance Distribution StdUniform Word64     where rvarT ~StdUniform = getRandomPrim PrimWord64
+instance Distribution StdUniform Word8      where rvarT _ = getRandomWord8
+instance Distribution StdUniform Word16     where rvarT _ = getRandomWord16
+instance Distribution StdUniform Word32     where rvarT _ = getRandomWord32
+instance Distribution StdUniform Word64     where rvarT _ = getRandomWord64
 
-instance Distribution StdUniform Int8       where rvarT ~StdUniform = fromIntegral `fmap` getRandomPrim PrimWord8
-instance Distribution StdUniform Int16      where rvarT ~StdUniform = fromIntegral `fmap` getRandomPrim PrimWord16
-instance Distribution StdUniform Int32      where rvarT ~StdUniform = fromIntegral `fmap` getRandomPrim PrimWord32
-instance Distribution StdUniform Int64      where rvarT ~StdUniform = fromIntegral `fmap` getRandomPrim PrimWord64
+instance Distribution StdUniform Int8       where rvarT _ = fromIntegral `fmap` getRandomWord8
+instance Distribution StdUniform Int16      where rvarT _ = fromIntegral `fmap` getRandomWord16
+instance Distribution StdUniform Int32      where rvarT _ = fromIntegral `fmap` getRandomWord32
+instance Distribution StdUniform Int64      where rvarT _ = fromIntegral `fmap` getRandomWord64
 
 instance Distribution StdUniform Int where
-    rvar ~StdUniform =
+    rvar _ =
         $(if toInteger (maxBound :: Int) > toInteger (maxBound :: Int32)
-            then [|fromIntegral `fmap` getRandomPrim PrimWord64|]
-            else [|fromIntegral `fmap` getRandomPrim PrimWord32|])
+            then [|fromIntegral `fmap` getRandomWord64 :: RVar Int|]
+            else [|fromIntegral `fmap` getRandomWord32 :: RVar Int|])
 
 instance Distribution StdUniform Word where
-    rvar ~StdUniform =
+    rvar _ =
         $(if toInteger (maxBound :: Word) > toInteger (maxBound :: Word32)
-            then [|fromIntegral `fmap` getRandomPrim PrimWord64|]
-            else [|fromIntegral `fmap` getRandomPrim PrimWord32|])
+            then [|fromIntegral `fmap` getRandomWord64 :: RVar Word|]
+            else [|fromIntegral `fmap` getRandomWord32 :: RVar Word|])
 
 -- Integer has no StdUniform...
 
@@ -318,15 +314,16 @@
 instance CDF StdUniform Int64   where cdf _ = integralUniformCDF minBound maxBound
 instance CDF StdUniform Int     where cdf _ = integralUniformCDF minBound maxBound
 
+
 instance Distribution Uniform Float         where rvarT (Uniform a b) = floatUniform  a b
 instance Distribution Uniform Double        where rvarT (Uniform a b) = doubleUniform a b
 instance CDF Uniform Float                  where cdf   (Uniform a b) = realUniformCDF a b
 instance CDF Uniform Double                 where cdf   (Uniform a b) = realUniformCDF a b
 
-instance Distribution StdUniform Float      where rvarT ~StdUniform = floatStdUniform
-instance Distribution StdUniform Double     where rvarT ~StdUniform = getRandomPrim PrimDouble; rvarT ~StdUniform = getRandomPrim PrimDouble
-instance CDF StdUniform Float               where cdf   ~StdUniform = realStdUniformCDF
-instance CDF StdUniform Double              where cdf   ~StdUniform = realStdUniformCDF
+instance Distribution StdUniform Float      where rvarT _ = floatStdUniform
+instance Distribution StdUniform Double     where rvarT _ = getRandomDouble
+instance CDF StdUniform Float               where cdf   _ = realStdUniformCDF
+instance CDF StdUniform Double              where cdf   _ = realStdUniformCDF
 
 instance HasResolution r => 
          Distribution Uniform (Fixed r)     where rvarT (Uniform a b) = fixedUniform  a b
@@ -347,7 +344,7 @@
 
 instance Distribution StdUniform ()         where rvarT ~StdUniform = return ()
 instance CDF StdUniform ()                  where cdf   ~StdUniform = return 1
-instance Distribution StdUniform Bool       where rvarT ~StdUniform = fmap even (getRandomPrim PrimWord8)
+instance Distribution StdUniform Bool       where rvarT ~StdUniform = fmap even (getRandomWord8)
 instance CDF StdUniform Bool                where cdf   ~StdUniform = boundedEnumStdUniformCDF
 
 instance Distribution StdUniform Char       where rvarT ~StdUniform = boundedEnumStdUniform
diff --git a/src/Data/Random/Distribution/Ziggurat.hs b/src/Data/Random/Distribution/Ziggurat.hs
--- a/src/Data/Random/Distribution/Ziggurat.hs
+++ b/src/Data/Random/Distribution/Ziggurat.hs
@@ -218,7 +218,7 @@
             (r,v) = findBin0 c f fInv fInt fVol
 
 -- |Build a lazy recursive ziggurat.  Uses a lazily-constructed ziggurat
--- as its tail distribution (with another as its tail, ad nauseum).
+-- as its tail distribution (with another as its tail, ad nauseam).
 -- 
 -- Arguments:
 -- 
@@ -251,7 +251,7 @@
 mkZigguratRec m f fInv fInt fVol c getIU = z
         where
             fix :: ((forall m. a -> RVarT m a) -> (forall m. a -> RVarT m a)) -> (forall m. a -> RVarT m a)
-            fix f = f (fix f)
+            fix g = g (fix g)
             z = mkZiggurat m f fInv fInt fVol c getIU (fix (mkTail m f fInv fInt fVol c getIU z))
 
 mkTail :: 
diff --git a/src/Data/Random/Internal/Primitives.hs b/src/Data/Random/Internal/Primitives.hs
deleted file mode 100644
--- a/src/Data/Random/Internal/Primitives.hs
+++ /dev/null
@@ -1,249 +0,0 @@
-{-# LANGUAGE GADTs, RankNTypes, DeriveDataTypeable #-}
--- |This is an experimental interface to support an extensible set of primitives,
--- where a RandomSource will be able to support whatever subset of them they want
--- and have well-founded defaults generated automatically for any unsupported
--- primitives.
---
--- The purpose, in case it's not clear, is to decouple the implementations of
--- entropy sources from any particular set of primitives, so that implementors
--- of random variates can make use of a large number of primitives, supported
--- on all entropy sources, while the burden on entropy-source implementors
--- is only to provide one or two basic primitives of their choice.
--- 
--- One challenge I foresee with this interface is optimization - different 
--- compilers or even different versions of GHC may treat this interface 
--- radically differently, making it very hard to achieve reliable performance
--- on all platforms.  It may even be that no compiler optimizes sufficiently
--- to make the flexibility this system provides worth the overhead.  I hope
--- this is not the case, but if it turns out to be a major problem, this
--- system may disappear or be modified in significant ways.
-module Data.Random.Internal.Primitives (Prim(..), getPrimWhere, decomposePrimWhere) where
-
-import Data.Random.Internal.Words
-import Data.Word
-import Data.Bits
-import Data.Typeable
-
-import Control.Monad.Prompt
-
--- |A 'Prompt' GADT describing a request for a primitive random variate.
--- Random variable definitions will request their entropy via these prompts,
--- and entropy sources will satisfy some or all of them.  The 'decomposePrimWhere'
--- function extends an entropy source's incomplete definition to a complete 
--- definition, essentially defining a very flexible implementation-defaulting
--- system.
--- 
--- Some possible future additions:
---    PrimFloat :: Prim Float
---    PrimInt :: Prim Int
---    PrimPair :: Prim a -> Prim b -> Prim (a :*: b)
---    PrimNormal :: Prim Double
---    PrimChoice :: [(Double :*: a)] -> Prim a
---
--- Unfortunately, I cannot get Haddock to accept my comments about the 
--- data constructors, but hopefully they should be reasonably self-explanatory.
-data Prim a where
-    -- An unsigned byte, uniformly distributed from 0 to 0xff
-    PrimWord8           :: Prim Word8
-    -- An unsigned 16-bit word, uniformly distributed from 0 to 0xffff
-    PrimWord16          :: Prim Word16
-    -- An unsigned 32-bit word, uniformly distributed from 0 to 0xffffffff
-    PrimWord32          :: Prim Word32
-    -- An unsigned 64-bit word, uniformly distributed from 0 to 0xffffffffffffffff
-    PrimWord64          :: Prim Word64
-    -- A double-precision float U, uniformly distributed 0 <= U < 1
-    PrimDouble          :: Prim Double
-    -- A uniformly distributed 'Integer' 0 <= U < 2^(8*n)
-    PrimNByteInteger    :: !Int -> Prim Integer
-    deriving (Typeable)
-
-instance Show (Prim a) where
-    showsPrec _p PrimWord8               = showString "PrimWord8"
-    showsPrec _p PrimWord16              = showString "PrimWord16"
-    showsPrec _p PrimWord32              = showString "PrimWord32"
-    showsPrec _p PrimWord64              = showString "PrimWord64"
-    showsPrec _p PrimDouble              = showString "PrimDouble"
-    showsPrec  p (PrimNByteInteger n)    = showParen (p > 10) (showString "PrimNByteInteger " . showsPrec 11 n)
-
--- |This function wraps up the most common calling convention for 'decomposePrimWhere'.
--- Given a predicate identifying \"supported\" 'Prim's, and a (possibly partial) 
--- function that maps those 'Prim's to implementations, derives a total function
--- mapping all 'Prim's to implementations.
-{-# INLINE getPrimWhere #-}
-{-# SPECIALIZE getPrimWhere :: Monad m => (forall t. Prim t -> Bool) -> (forall t. Prim t -> m t) -> Prim Word8   -> m Word8   #-}
-{-# SPECIALIZE getPrimWhere :: Monad m => (forall t. Prim t -> Bool) -> (forall t. Prim t -> m t) -> Prim Word16  -> m Word16  #-}
-{-# SPECIALIZE getPrimWhere :: Monad m => (forall t. Prim t -> Bool) -> (forall t. Prim t -> m t) -> Prim Word32  -> m Word32  #-}
-{-# SPECIALIZE getPrimWhere :: Monad m => (forall t. Prim t -> Bool) -> (forall t. Prim t -> m t) -> Prim Word64  -> m Word64  #-}
-{-# SPECIALIZE getPrimWhere :: Monad m => (forall t. Prim t -> Bool) -> (forall t. Prim t -> m t) -> Prim Double  -> m Double  #-}
-{-# SPECIALIZE getPrimWhere :: Monad m => (forall t. Prim t -> Bool) -> (forall t. Prim t -> m t) -> Prim Integer -> m Integer #-}
-getPrimWhere :: Monad m => (forall t. Prim t -> Bool) -> (forall t. Prim t -> m t) -> Prim a -> m a
-getPrimWhere supported getPrim prim = runPromptM getPrim (decomposePrimWhere supported prim)
-
--- |This is essentially a suite of interrelated default implementations,
--- each definition making use of only \"supported\" primitives.  It _really_
--- ought to be inlined to the point where the @supported@ predicate
--- is able to be inlined into it and eliminated.  
--- 
--- When inlined sufficiently, it should in theory be optimized down to the
--- static set of "best" definitions for each required primitive in terms of 
--- only supported primitives.
--- 
--- Hopefully it does not impose too much overhead when not inlined.
-{-# INLINE decomposePrimWhere #-}
-{-# SPECIALIZE decomposePrimWhere :: (forall t. Prim t -> Bool) -> Prim Word8   -> Prompt Prim Word8   #-}
-{-# SPECIALIZE decomposePrimWhere :: (forall t. Prim t -> Bool) -> Prim Word16  -> Prompt Prim Word16  #-}
-{-# SPECIALIZE decomposePrimWhere :: (forall t. Prim t -> Bool) -> Prim Word32  -> Prompt Prim Word32  #-}
-{-# SPECIALIZE decomposePrimWhere :: (forall t. Prim t -> Bool) -> Prim Word64  -> Prompt Prim Word64  #-}
-{-# SPECIALIZE decomposePrimWhere :: (forall t. Prim t -> Bool) -> Prim Double  -> Prompt Prim Double  #-}
-{-# SPECIALIZE decomposePrimWhere :: (forall t. Prim t -> Bool) -> Prim Integer -> Prompt Prim Integer #-}
-decomposePrimWhere :: (forall t. Prim t -> Bool) -> Prim a -> Prompt Prim a
-decomposePrimWhere supported requested = decomp requested
-    where
-        {-# INLINE decomp #-}
-
-        {-# SPECIALIZE decomp :: Prim Word8   -> Prompt Prim Word8   #-}
-        {-# SPECIALIZE decomp :: Prim Word16  -> Prompt Prim Word16  #-}
-        {-# SPECIALIZE decomp :: Prim Word32  -> Prompt Prim Word32  #-}
-        {-# SPECIALIZE decomp :: Prim Word64  -> Prompt Prim Word64  #-}
-        {-# SPECIALIZE decomp :: Prim Double  -> Prompt Prim Double  #-}
-        {-# SPECIALIZE decomp :: Prim Integer -> Prompt Prim Integer #-}
-        -- First, all supported prims should just be evaluated directly.
-        decomp :: Prim a -> Prompt Prim a
-        decomp prim
-            | supported prim = prompt prim
-        -- beyond this point, all definitions must be in terms of
-        -- 'prompt's referring to other supported primitives or 
-        -- 'decomp's referring to other primitives in a well-founded way
-        
-        decomp PrimWord8
-            | supported PrimWord16 = do
-                w <- prompt PrimWord16
-                return (fromIntegral w)
-            | supported PrimWord32 = do
-                w <- prompt PrimWord32
-                return (fromIntegral w)
-            | supported PrimWord64 = do
-                w <- prompt PrimWord64
-                return (fromIntegral w)
-            | supported PrimDouble = do
-                d <- prompt PrimDouble
-                return (truncate (d * 256))
-            | supported (PrimNByteInteger 1) = do
-                i <- prompt (PrimNByteInteger 1)
-                return (fromInteger i)
-        
-        decomp PrimWord16
-            | supported PrimWord8 = do
-                b0 <- prompt PrimWord8
-                b1 <- prompt PrimWord8
-                return (buildWord16 b0 b1)
-            | supported PrimWord32 = do
-                w <- prompt PrimWord32
-                return (fromIntegral w)
-            | supported PrimWord64 = do
-                w <- prompt PrimWord64
-                return (fromIntegral w)
-            | supported PrimDouble = do
-                d <- prompt PrimDouble
-                return (truncate (d * 65536))
-            | supported (PrimNByteInteger 2) = do
-                i <- prompt (PrimNByteInteger 2)
-                return (fromInteger i)
-        
-        decomp PrimWord32
-            | supported PrimWord16 = do
-                w0 <- prompt PrimWord16
-                w1 <- prompt PrimWord16
-                
-                return (buildWord32' w0 w1)
-            | supported PrimWord8 = do
-                b0 <- prompt PrimWord8
-                b1 <- prompt PrimWord8
-                b2 <- prompt PrimWord8
-                b3 <- prompt PrimWord8
-                
-                return (buildWord32 b0 b1 b2 b3)
-            | supported PrimWord64 = do
-                w <- prompt PrimWord64
-                return (fromIntegral w)
-            | supported PrimDouble = do
-                d <- prompt PrimDouble
-                return (truncate (d * 4294967296))
-            | supported (PrimNByteInteger 4) = do
-                i <- prompt (PrimNByteInteger 4)
-                return (fromInteger i)
-        
-        decomp PrimWord64
-            | supported PrimWord32 = do
-                w0 <- prompt PrimWord32
-                w1 <- prompt PrimWord32
-                
-                return (buildWord64'' w0 w1)
-            | supported PrimWord16 = do
-                w0 <- prompt PrimWord16
-                w1 <- prompt PrimWord16
-                w2 <- prompt PrimWord16
-                w3 <- prompt PrimWord16
-                
-                return (buildWord64' w0 w1 w2 w3)
-            | supported PrimWord8 = do
-                b0 <- prompt PrimWord8
-                b1 <- prompt PrimWord8
-                b2 <- prompt PrimWord8
-                b3 <- prompt PrimWord8
-                b4 <- prompt PrimWord8
-                b5 <- prompt PrimWord8
-                b6 <- prompt PrimWord8
-                b7 <- prompt PrimWord8
-                
-                return (buildWord64 b0 b1 b2 b3 b4 b5 b6 b7)
-            | supported PrimDouble = do
-                -- Need 2 doubles, because a uniform [0,1) double only has
-                -- about 52 bits of reliable entropy
-                d0 <- prompt PrimDouble
-                d1 <- prompt PrimDouble
-                
-                let w0 = truncate (d0 * 4294967296)
-                    w1 = truncate (d1 * 4294967296)
-                
-                return (w0 .|. (w1 `shiftL` 32))
-            | supported (PrimNByteInteger 8) = do
-                i <- prompt (PrimNByteInteger 8)
-                return (fromInteger i)
-        
-        decomp PrimDouble = do
-            word <- decomp PrimWord64
-            return (wordToDouble word)
-        
-        decomp (PrimNByteInteger 1) = do
-            x <- decomp PrimWord8
-            return $! toInteger x
-        decomp (PrimNByteInteger 2) = do
-            x <- decomp PrimWord16
-            return $! toInteger x
-        decomp (PrimNByteInteger 4) = do
-            x <- decomp PrimWord32
-            return $! toInteger x
-        decomp (PrimNByteInteger 8) = do
-            x <- decomp PrimWord64
-            return $! toInteger x
-        decomp (PrimNByteInteger (n+8))  = do
-            x <- decomp PrimWord64
-            y <- decomp (PrimNByteInteger n)
-            return $! (toInteger x `shiftL` (n `shiftL` 3)) .|. y
-        decomp (PrimNByteInteger (n+4))  = do
-            x <- decomp PrimWord32
-            y <- decomp (PrimNByteInteger n)
-            return $! (toInteger x `shiftL` (n `shiftL` 3)) .|. y
-        decomp (PrimNByteInteger (n+2))  = do
-            x <- decomp PrimWord16
-            y <- decomp (PrimNByteInteger n)
-            return $! (toInteger x `shiftL` (n `shiftL` 3)) .|. y
--- REDUNDANT CASE
---        decomp (PrimNByteInteger (n+1))  = do
---            x <- decomp PrimWord8
---            y <- decomp (PrimNByteInteger n)
---            return $! (toInteger x `shiftL` (n `shiftL` 3)) .|. y
-        decomp (PrimNByteInteger _) = return 0
-        
-        decomp _ = error ("decomposePrimWhere: no supported primitive to satisfy " ++ show requested)
diff --git a/src/Data/Random/Internal/TH.hs b/src/Data/Random/Internal/TH.hs
--- a/src/Data/Random/Internal/TH.hs
+++ b/src/Data/Random/Internal/TH.hs
@@ -1,6 +1,3 @@
-{-
- -      ``Data/Random/Internal/TH''
- -}
 {-# LANGUAGE
         TemplateHaskell
   #-}
diff --git a/src/Data/Random/Internal/Words.hs b/src/Data/Random/Internal/Words.hs
deleted file mode 100644
--- a/src/Data/Random/Internal/Words.hs
+++ /dev/null
@@ -1,128 +0,0 @@
-{-
- -      ``Data/Random/Internal/Words''
- -}
-
--- |A few little functions I found myself writing inline over and over again.
-module Data.Random.Internal.Words where
-
-import Foreign
-
--- TODO: add a build flag for endianness-invariance, or just find a way
--- to make sure these operations all do the right thing without costing 
--- anything extra at runtime
-
-{-# INLINE buildWord16 #-}
--- |Build a word out of 2 bytes.  No promises are made regarding the order
--- in which the bytes are stuffed.  Note that this means that a 'RandomSource'
--- or 'MonadRandom' making use of the default definition of 'getRandomWord', etc.,
--- may return different random values on different platforms when started 
--- with the same seed, depending on the platform's endianness.
-buildWord16 :: Word8 -> Word8 -> Word16
-buildWord16 b0 b1
-    = unsafePerformIO . allocaBytes 2 $ \p -> do
-        pokeByteOff p 0 b0
-        pokeByteOff p 1 b1
-        peek (castPtr p)
-
-{-# INLINE buildWord32 #-}
--- |Build a word out of 4 bytes.  No promises are made regarding the order
--- in which the bytes are stuffed.  Note that this means that a 'RandomSource'
--- or 'MonadRandom' making use of the default definition of 'getRandomWord', etc.,
--- may return different random values on different platforms when started 
--- with the same seed, depending on the platform's endianness.
-buildWord32 :: Word8 -> Word8 -> Word8 -> Word8 -> Word32
-buildWord32 b0 b1 b2 b3
-    = unsafePerformIO . allocaBytes 4 $ \p -> do
-        pokeByteOff p 0 b0
-        pokeByteOff p 1 b1
-        pokeByteOff p 2 b2
-        pokeByteOff p 3 b3
-        peek (castPtr p)
-
-{-# INLINE buildWord32' #-}
-buildWord32' :: Word16 -> Word16 -> Word32
-buildWord32' w0 w1
-    = unsafePerformIO . allocaBytes 4 $ \p -> do
-        pokeByteOff p 0 w0
-        pokeByteOff p 2 w1
-        peek (castPtr p)
-
-{-# INLINE buildWord64 #-}
--- |Build a word out of 8 bytes.  No promises are made regarding the order
--- in which the bytes are stuffed.  Note that this means that a 'RandomSource'
--- or 'MonadRandom' making use of the default definition of 'getRandomWord', etc.,
--- may return different random values on different platforms when started 
--- with the same seed, depending on the platform's endianness.
-buildWord64 :: Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word64
-buildWord64 b0 b1 b2 b3 b4 b5 b6 b7
-    = unsafePerformIO . allocaBytes 8 $ \p -> do
-        pokeByteOff p 0 b0
-        pokeByteOff p 1 b1
-        pokeByteOff p 2 b2
-        pokeByteOff p 3 b3
-        pokeByteOff p 4 b4
-        pokeByteOff p 5 b5
-        pokeByteOff p 6 b6
-        pokeByteOff p 7 b7
-        peek (castPtr p)
-
-{-# INLINE buildWord64' #-}
-buildWord64' :: Word16 -> Word16 -> Word16 -> Word16 -> Word64
-buildWord64' w0 w1 w2 w3
-    = unsafePerformIO . allocaBytes 8 $ \p -> do
-        pokeByteOff p 0 w0
-        pokeByteOff p 2 w1
-        pokeByteOff p 4 w2
-        pokeByteOff p 6 w3
-        peek (castPtr p)
-
-{-# INLINE buildWord64'' #-}
-buildWord64'' :: Word32 -> Word32 -> Word64
-buildWord64'' w0 w1
-    = unsafePerformIO . allocaBytes 8 $ \p -> do
-        pokeByteOff p 0 w0
-        pokeByteOff p 4 w1
-        peek (castPtr p)
-
-{-# INLINE word32ToFloat #-}
--- |Pack the low 23 bits from a 'Word32' into a 'Float' in the range [0,1).
--- Used to convert a 'stdUniform' 'Word32' to a 'stdUniform' 'Double'.
-word32ToFloat :: Word32 -> Float
-word32ToFloat x = (encodeFloat $! toInteger (x .&. 0x007fffff {- 2^23-1 -} )) $ (-23)
-
-{-# INLINE word32ToFloatWithExcess #-}
--- |Same as word32ToFloat, but also return the unused bits (as the 9
--- least significant bits of a 'Word32')
-word32ToFloatWithExcess :: Word32 -> (Float, Word32)
-word32ToFloatWithExcess x = (word32ToFloat x, x `shiftR` 23)
-
-{-# INLINE wordToFloat #-}
--- |Pack the low 23 bits from a 'Word64' into a 'Float' in the range [0,1).
--- Used to convert a 'stdUniform' 'Word64' to a 'stdUniform' 'Double'.
-wordToFloat :: Word64 -> Float
-wordToFloat x = (encodeFloat $! toInteger (x .&. 0x007fffff {- 2^23-1 -} )) $ (-23)
-
-{-# INLINE wordToFloatWithExcess #-}
--- |Same as wordToFloat, but also return the unused bits (as the 41
--- least significant bits of a 'Word64')
-wordToFloatWithExcess :: Word64 -> (Float, Word64)
-wordToFloatWithExcess x = (wordToFloat x, x `shiftR` 23)
-
-{-# INLINE wordToDouble #-}
--- |Pack the low 52 bits from a 'Word64' into a 'Double' in the range [0,1).
--- Used to convert a 'stdUniform' 'Word64' to a 'stdUniform' 'Double'.
-wordToDouble :: Word64 -> Double
-wordToDouble x = (encodeFloat $! toInteger (x .&. 0x000fffffffffffff {- 2^52-1 -})) $ (-52)
-
-{-# INLINE word32ToDouble #-}
--- |Pack a 'Word32' into a 'Double' in the range [0,1).  Note that a Double's 
--- mantissa is 52 bits, so this does not fill all of them.
-word32ToDouble :: Word32 -> Double
-word32ToDouble x = (encodeFloat $! toInteger x) $ (-32)
-
-{-# INLINE wordToDoubleWithExcess #-}
--- |Same as wordToDouble, but also return the unused bits (as the 12
--- least significant bits of a 'Word64')
-wordToDoubleWithExcess :: Word64 -> (Double, Word64)
-wordToDoubleWithExcess x = (wordToDouble x, x `shiftR` 52)
-
diff --git a/src/Data/Random/Lift.hs b/src/Data/Random/Lift.hs
--- a/src/Data/Random/Lift.hs
+++ b/src/Data/Random/Lift.hs
@@ -1,10 +1,16 @@
-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, IncoherentInstances #-}
+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, IncoherentInstances, CPP #-}
 
 module Data.Random.Lift where
 
-import Control.Monad.Identity
-import qualified Control.Monad.Trans as T
+import Data.RVar
+import qualified Data.Functor.Identity as T
+import qualified Control.Monad.Trans.Class as T
+import Data.Random.Source.Std
 
+#ifndef MTL2
+import qualified Control.Monad.Identity as MTL
+#endif
+
 -- | A class for \"liftable\" data structures. Conceptually
 -- an extension of 'T.MonadTrans' to allow deep lifting,
 -- but lifting need not be done between monads only. Eg lifting
@@ -31,5 +37,22 @@
 -- | This instance is incoherent with the other two. However,
 -- by the law @lift (return x) == return x@, the results
 -- must always be the same.
-instance Monad m => Lift Identity m where
-    lift = return . runIdentity
+instance Monad m => Lift T.Identity m where
+    lift = return . T.runIdentity
+
+instance Lift (RVarT T.Identity) (RVarT m) where
+    lift x = runRVar x StdRandom
+
+#ifndef MTL2
+
+-- | This instance is incoherent with the other two. However,
+-- by the law @lift (return x) == return x@, the results
+-- must always be the same.
+instance Monad m => Lift MTL.Identity m where
+    lift = return . MTL.runIdentity
+
+instance Lift (RVarT MTL.Identity) (RVarT m) where
+    lift x = runRVar x StdRandom
+
+#endif
+
diff --git a/src/Data/Random/List.hs b/src/Data/Random/List.hs
--- a/src/Data/Random/List.hs
+++ b/src/Data/Random/List.hs
@@ -36,7 +36,7 @@
 shuffleNofM 0 _ _ = return []
 shuffleNofM n m xs
     | n > m     = error "shuffleNofM: n > m"
-    | otherwise = do
+    | n >= 0    = do
         is <- sequence [uniform 0 i | i <- take n [m-1, m-2 ..1]]
         return (take n $ SRS.shuffle (take m xs) is)
 shuffleNofM _ _ _ = error "shuffleNofM: negative length specified"
diff --git a/src/Data/Random/RVar.hs b/src/Data/Random/RVar.hs
--- a/src/Data/Random/RVar.hs
+++ b/src/Data/Random/RVar.hs
@@ -1,222 +1,14 @@
-{-
- -      ``Data/Random/RVar''
- -}
-{-# LANGUAGE
-    RankNTypes,
-    MultiParamTypeClasses,
-    FlexibleInstances, 
-    GADTs,
-    ScopedTypeVariables
-  #-}
-
--- |Random variables.  An 'RVar' is a sampleable random variable.  Because
--- probability distributions form a monad, they are quite easy to work with
--- in the standard Haskell monadic styles.  For examples, see the source for
--- any of the 'Distribution' instances - they all are defined in terms of
--- 'RVar's.
+{-# LANGUAGE RankNTypes, FlexibleInstances, MultiParamTypeClasses #-}
 module Data.Random.RVar
-    ( RVar
-    , runRVar
-    , RVarT
-    , runRVarT
-    , runRVarTWith
+    ( RVar, runRVar
+    , RVarT, runRVarT, runRVarTWith
     ) where
 
-
-import Data.Random.Internal.Primitives
-import Data.Random.Source
-import Data.Random.Lift as L
-
-import qualified Control.Monad.Trans as T
-import Control.Applicative
-import Control.Monad.Identity
-import Control.Monad.Prompt (PromptT, runPromptT, prompt)
-
--- |An opaque type modeling a \"random variable\" - a value 
--- which depends on the outcome of some random event.  'RVar's 
--- can be conveniently defined by an imperative-looking style:
--- 
--- > normalPair =  do
--- >     u <- stdUniform
--- >     t <- stdUniform
--- >     let r = sqrt (-2 * log u)
--- >         theta = (2 * pi) * t
--- >         
--- >         x = r * cos theta
--- >         y = r * sin theta
--- >     return (x,y)
--- 
--- OR by a more applicative style:
--- 
--- > logNormal = exp <$> stdNormal
---
--- Once defined (in any style), there are several ways to sample 'RVar's:
--- 
--- * In a monad, using a 'RandomSource':
--- 
--- > sampleFrom DevRandom (uniform 1 100) :: IO Int
--- 
--- * In a monad, using a 'MonadRandom' instance:
---
--- > sample (uniform 1 100) :: State PureMT Int
--- 
--- * As a pure function transforming a functional RNG:
--- 
--- > sampleState (uniform 1 100) :: StdGen -> (Int, StdGen)
-type RVar = RVarT Identity
-
--- |\"Run\" an 'RVar' - samples the random variable from the provided
--- source of entropy.  Typically 'sample', 'sampleFrom' or 'sampleState' will
--- be more convenient to use.
-runRVar :: RandomSource m s => RVar a -> s -> m a
-runRVar = runRVarT
-
--- |A random variable with access to operations in an underlying monad.  Useful
--- examples include any form of state for implementing random processes with hysteresis,
--- or writer monads for implementing tracing of complicated algorithms.
--- 
--- For example, a simple random walk can be implemented as an 'RVarT' 'IO' value:
---
--- > rwalkIO :: IO (RVarT IO Double)
--- > rwalkIO d = do
--- >     lastVal <- newIORef 0
--- >     
--- >     let x = do
--- >             prev    <- lift (readIORef lastVal)
--- >             change  <- rvarT StdNormal
--- >             
--- >             let new = prev + change
--- >             lift (writeIORef lastVal new)
--- >             return new
--- >         
--- >     return x
---
--- To run the random walk, it must first be initialized, and then it can be sampled as usual:
---
--- > do
--- >     rw <- rwalkIO
--- >     x <- sampleFrom DevURandom rw
--- >     y <- sampleFrom DevURandom rw
--- >     ...
---
--- The same random-walk process as above can be implemented using MTL types
--- as follows (using @import Control.Monad.Trans as MTL@):
--- 
--- > rwalkState :: RVarT (State Double) Double
--- > rwalkState = do
--- >     prev <- MTL.lift get
--- >     change  <- rvarT StdNormal
--- >     
--- >     let new = prev + change
--- >     MTL.lift (put new)
--- >     return new
--- 
--- Invocation is straightforward (although a bit noisy) if you're used 
--- to MTL, but there is a gotcha lurking here: @sample@ and 'runRVarT' 
--- inherit the extreme generality of 'lift', so there will almost always
--- need to be an explicit type signature lurking somewhere in any client 
--- code making use of 'RVarT' with MTL types.  In this example, the 
--- inferred type of @start@ would be too general to be practical, so the
--- signature for @rwalk@  explicitly fixes it to 'Double'.  Alternatively, 
--- in this case @sample@ could be replaced with
--- @\\x -> runRVarTWith MTL.lift x StdRandom@.
--- 
--- > rwalk :: Int -> Double -> StdGen -> ([Double], StdGen)
--- > rwalk count start gen = evalState (runStateT (sample (replicateM count rwalkState)) gen) start
-newtype RVarT m a = RVarT { unRVarT :: PromptT Prim m a }
-
--- | \"Runs\" an 'RVarT', sampling the random variable it defines.
--- 
--- The 'Lift' context allows random variables to be defined using a minimal
--- underlying functor ('Identity' is sufficient for \"conventional\" random
--- variables) and then sampled in any monad into which the underlying functor 
--- can be embedded (which, for 'Identity', is all monads).
--- 
--- The lifting is very important - without it, every 'RVar' would have
--- to either be given access to the full capability of the monad in which it
--- will eventually be sampled (which, incidentally, would also have to be 
--- monomorphic so you couldn't sample one 'RVar' in more than one monad)
--- or functions manipulating 'RVar's would have to use higher-ranked 
--- types to enforce the same kind of isolation and polymorphism.
--- 
--- For non-standard liftings or those where you would rather not introduce a
--- 'Lift' instance, see 'runRVarTWith'.
-{-# INLINE runRVarT #-}
-runRVarT :: 
-    forall n m s a.
-    (Lift n m, RandomSource m s) 
-    => RVarT n a -> s -> m a
-runRVarT (RVarT m) src = runPromptT return bindP bindN m
-    where
-        bindP :: forall t x. Prim t -> (t -> m x) -> m x
-        bindP prim cont = getRandomPrimFrom src prim >>= cont
-        bindN :: forall t x. n t    -> (t -> m x) -> m x
-        bindN nExp cont = lift nExp >>= cont
-
--- |Like 'runRVarT' but allowing a user-specified lift operation.  This 
--- operation must obey the \"monad transformer\" laws:
---
--- > lift . return = return
--- > lift (x >>= f) = (lift x) >>= (lift . f)
---
--- One example of a useful non-standard lifting would be one that takes @State s@ to
--- another monad with a different state representation (such as @IO@ with the
--- state mapped to an @IORef@):
---
--- > embedState :: (Monad m) => m s -> (s -> m ()) -> State s a -> m a
--- > embedState get put = \m -> do
--- >     s <- get
--- >     (res,s) <- return (runState m s)
--- >     put s
--- >     return res
-{-# INLINE runRVarTWith #-}
-runRVarTWith :: 
-    forall n m s a.
-    (RandomSource m s) 
-    => (forall t. n t -> m t) -> RVarT n a -> s -> m a
-runRVarTWith liftN (RVarT m) src = runPromptT return bindP bindN m
-    where
-        bindP :: forall t x. Prim t -> (t -> m x) -> m x
-        bindP prim cont = getRandomPrimFrom src prim >>= cont
-        bindN :: forall t x. n t    -> (t -> m x) -> m x
-        bindN nExp cont = liftN nExp >>= cont
-
-instance Functor (RVarT n) where
-    fmap = liftM
-
-instance Monad (RVarT n) where
-    return x = RVarT (return $! x)
-    fail s   = RVarT (fail s)
-    (RVarT m) >>= k = RVarT (m >>= \x -> x `seq` unRVarT (k x))
-
-instance Applicative (RVarT n) where
-    pure  = return
-    (<*>) = ap
-
-instance T.MonadTrans RVarT where
-    lift m = RVarT (T.lift m)
-
-instance Lift (RVarT Identity) (RVarT m) where
-    lift (RVarT m) = RVarT (runPromptT return bindP bindN m)
-        where
-            bindP :: Prim a     -> (a -> PromptT Prim m b) -> PromptT Prim m b
-            bindP prim  cont = prompt prim >>= cont
-            bindN :: Identity a -> (a -> PromptT Prim m b) -> PromptT Prim m b
-            bindN idExp cont = cont (runIdentity idExp)
-
-instance T.MonadIO m => T.MonadIO (RVarT m) where
-    liftIO = T.lift . T.liftIO
-
-instance MonadRandom (RVarT n) where
-    getRandomPrim p = RVarT (prompt p)
+import Data.Random.Lift
+import Data.Random.Internal.Source
+import Data.RVar hiding (runRVarT)
 
--- I would really like to be able to do this, but I can't because of the
--- blasted Eq and Show in Num's class context...
--- instance (Applicative m, Num a) => Num (RVarT m a) where
---     (+) = liftA2 (+)
---     (-) = liftA2 (-)
---     (*) = liftA2 (*)
---     negate = liftA negate
---     signum = liftA signum
---     abs = liftA abs
---     fromInteger = pure . fromInteger
+-- |Like 'runRVarTWith', but using an implicit lifting (provided by the 
+-- 'Lift' class)
+runRVarT :: (Lift n m, RandomSource m s) => RVarT n a -> s -> m a
+runRVarT = runRVarTWith lift
diff --git a/src/Data/Random/Sample.hs b/src/Data/Random/Sample.hs
--- a/src/Data/Random/Sample.hs
+++ b/src/Data/Random/Sample.hs
@@ -1,6 +1,3 @@
-{-
- -      ``Data/Random/Sample''
- -}
 {-# LANGUAGE
         MultiParamTypeClasses,
         FlexibleInstances, FlexibleContexts, 
diff --git a/src/Data/Random/Source.hs b/src/Data/Random/Source.hs
deleted file mode 100644
--- a/src/Data/Random/Source.hs
+++ /dev/null
@@ -1,100 +0,0 @@
-{-
- -      ``Data/Random/Source''
- -}
-{-# LANGUAGE
-    MultiParamTypeClasses, FlexibleInstances, GADTs
-  #-}
-
-module Data.Random.Source
-    ( MonadRandom(..)
-    , RandomSource(..)
-    , Prim(..)
-    ) where
-
-import Data.Word
-
-import Data.Random.Internal.Primitives
-
--- |A typeclass for monads with a chosen source of entropy.  For example,
--- 'RVar' is such a monad - the source from which it is (eventually) sampled
--- is the only source from which a random variable is permitted to draw, so
--- when directly requesting entropy for a random variable these functions
--- are used.
--- 
--- Occasionally one might want a 'RandomSource' specifying the 'MonadRandom'
--- instance (for example, when using 'runRVar').  For those cases, 
--- "Data.Random.Source.Std".'StdRandom' provides a 'RandomSource' that
--- maps to the 'MonadRandom' instance.
--- 
--- For example, @State StdGen@ has a 'MonadRandom' instance, so to run an
--- 'RVar' (called @x@ in this example) in this monad one could write
--- @runRVar x StdRandom@ (or more concisely with the 'sample' function: @sample x@).
--- 
-class Monad m => MonadRandom m where
-    -- |Generate a random value corresponding to the specified primitive.
-    -- The 'Prim' type has many variants, and is also somewhat unstable.
-    -- 'getPrimWhere' is a useful function for abstracting over the type,
-    -- semi-automatically extending a partial implementation to the full
-    -- 'Prim' type.
-    getRandomPrim :: Prim t -> m t
-
--- |A source of entropy which can be used in the given monad.
--- 
--- See also 'MonadRandom'.
-class Monad m => RandomSource m s where
-    -- |Generate a random value corresponding to the specified primitive.
-    -- The 'Prim' type has many variants, and is also somewhat unstable.
-    -- 'getPrimWhere' is a useful function for abstracting over the type,
-    -- semi-automatically extending a partial implementation to the full
-    -- 'Prim' type.
-    getRandomPrimFrom :: s -> Prim t -> m t
-
-instance Monad m => RandomSource m (m Word8) where
-    getRandomPrimFrom f = getPrimWhere supported (getPrim f)
-        where
-            supported :: Prim a -> Bool
-            supported PrimWord8 = True
-            supported _ = False
-            
-            getPrim :: m Word8 -> Prim a -> m a
-            getPrim f PrimWord8 = f
-
-instance Monad m => RandomSource m (m Word16) where
-    getRandomPrimFrom f = getPrimWhere supported (getPrim f)
-        where
-            supported :: Prim a -> Bool
-            supported PrimWord16 = True
-            supported _ = False
-            
-            getPrim :: m Word16 -> Prim a -> m a
-            getPrim f PrimWord16 = f
-
-instance Monad m => RandomSource m (m Word32) where
-    getRandomPrimFrom f = getPrimWhere supported (getPrim f)
-        where
-            supported :: Prim a -> Bool
-            supported PrimWord32 = True
-            supported _ = False
-            
-            getPrim :: m Word32 -> Prim a -> m a
-            getPrim f PrimWord32 = f
-
-instance Monad m => RandomSource m (m Word64) where
-    getRandomPrimFrom f = getPrimWhere supported (getPrim f)
-        where
-            supported :: Prim a -> Bool
-            supported PrimWord64 = True
-            supported _ = False
-            
-            getPrim :: m Word64 -> Prim a -> m a
-            getPrim f PrimWord64 = f
-
-instance Monad m => RandomSource m (m Double) where
-    getRandomPrimFrom f = getPrimWhere supported (getPrim f)
-        where
-            supported :: Prim a -> Bool
-            supported PrimDouble = True
-            supported _ = False
-            
-            getPrim :: m Double -> Prim a -> m a
-            getPrim f PrimDouble = f
diff --git a/src/Data/Random/Source/DevRandom.hs b/src/Data/Random/Source/DevRandom.hs
deleted file mode 100644
--- a/src/Data/Random/Source/DevRandom.hs
+++ /dev/null
@@ -1,62 +0,0 @@
-{-
- -      ``Data/Random/Source/DevRandom''
- -}
-{-# LANGUAGE
-    MultiParamTypeClasses, GADTs
-  #-}
-
-module Data.Random.Source.DevRandom 
-    ( DevRandom(..)
-    ) where
-
-import Data.Random.Source
-import Data.Random.Internal.Primitives
-
-import System.IO (openBinaryFile, hGetBuf, Handle, IOMode(..))
-import Foreign
-
--- |On systems that have it, \/dev\/random is a handy-dandy ready-to-use source
--- of nonsense.  Keep in mind that on some systems, Linux included, \/dev\/random
--- collects \"real\" entropy, and if you don't have a good source of it, such as
--- special hardware for the purpose or a *lot* of network traffic, it's pretty easy
--- to suck the entropy pool dry with entropy-intensive applications.  For many
--- purposes other than cryptography, \/dev\/urandom is preferable because when it
--- runs out of real entropy it'll still churn out pseudorandom data.
-data DevRandom = DevRandom | DevURandom
-    deriving (Eq, Show)
-
-{-# NOINLINE devRandom  #-}
-devRandom :: Handle
-devRandom  = unsafePerformIO (openBinaryFile "/dev/random"  ReadMode)
-{-# NOINLINE devURandom #-}
-devURandom :: Handle
-devURandom = unsafePerformIO (openBinaryFile "/dev/urandom" ReadMode)
-
-dev :: DevRandom -> Handle
-dev DevRandom  = devRandom
-dev DevURandom = devURandom
-
-instance RandomSource IO DevRandom where
-    getRandomPrimFrom src = getPrimWhere supported getPrim
-        where
-            supported :: Prim a -> Bool
-            supported PrimWord8          = True
-            supported PrimWord16         = True
-            supported PrimWord32         = True
-            supported PrimWord64         = True
-            supported _ = False
-            
-            getPrim :: Prim a -> IO a
-            getPrim PrimWord8  = allocaBytes 1 $ \buf -> do
-                1 <- hGetBuf (dev src) buf  1
-                peek buf
-            getPrim PrimWord16 = allocaBytes 2 $ \buf -> do
-                2 <- hGetBuf (dev src) buf  2
-                peek (castPtr buf)
-            getPrim PrimWord32  = allocaBytes 4 $ \buf -> do
-                4 <- hGetBuf (dev src) buf  4
-                peek (castPtr buf)
-            getPrim PrimWord64  = allocaBytes 8 $ \buf -> do
-                8 <- hGetBuf (dev src) buf  8
-                peek (castPtr buf)
-            getPrim prim = error ("getRandomPrimFrom/" ++ show src ++ ": unsupported prim requested: " ++ show prim)
diff --git a/src/Data/Random/Source/MWC.hs b/src/Data/Random/Source/MWC.hs
deleted file mode 100644
--- a/src/Data/Random/Source/MWC.hs
+++ /dev/null
@@ -1,41 +0,0 @@
-{-# LANGUAGE
-        MultiParamTypeClasses,
-        FlexibleInstances,
-        GADTs
-  #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
--- |This module defines the following instances:
--- 
--- > instance RandomSource (ST s) (Gen s)
--- > instance RandomSource IO (Gen RealWorld)
-module Data.Random.Source.MWC where
-
-import Data.Random.Internal.Primitives
-import Data.Random.Internal.Words
-import Data.Random.Source
-import System.Random.MWC
-import Control.Monad.ST
-
-instance RandomSource (ST s) (Gen s) where
-    getRandomPrimFrom src = getPrimWhere supported (getPrim src)
-        where
-            {-# INLINE supported #-}
-            supported :: Prim a -> Bool
-            supported PrimWord8  = True
-            supported PrimWord16 = True
-            supported PrimWord32 = True
-            supported PrimWord64 = True
-            supported PrimDouble = True
-            supported _ = False
-    
-            {-# INLINE getPrim #-}
-            getPrim :: Gen s -> Prim a -> ST s a
-            getPrim gen PrimWord8    = uniform gen
-            getPrim gen PrimWord16   = uniform gen
-            getPrim gen PrimWord32   = uniform gen
-            getPrim gen PrimWord64   = uniform gen
-            getPrim gen PrimDouble   = fmap wordToDouble (uniform gen)
-            getPrim gen p            = error ("getSupportedRandomPrimFrom/Gen s: unsupported prim requested: " ++ show p)
-
-instance RandomSource IO (Gen RealWorld) where
-    getRandomPrimFrom src = stToIO . getRandomPrimFrom src
diff --git a/src/Data/Random/Source/PureMT.hs b/src/Data/Random/Source/PureMT.hs
deleted file mode 100644
--- a/src/Data/Random/Source/PureMT.hs
+++ /dev/null
@@ -1,168 +0,0 @@
-{-# LANGUAGE
-    CPP,
-    BangPatterns,
-    MultiParamTypeClasses,
-    FlexibleContexts, FlexibleInstances,
-    UndecidableInstances,
-    GADTs, RankNTypes,
-    ScopedTypeVariables
-  #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-
--- |This module provides functions useful for implementing new 'MonadRandom'
--- and 'RandomSource' instances for state-abstractions containing 'PureMT'
--- values (the pure pseudorandom generator provided by the
--- mersenne-random-pure64 package), as well as instances for some common
--- cases.
--- 
--- A 'PureMT' generator is immutable, so 'PureMT' by itself cannot be a 
--- 'RandomSource' (if it were, it would always give the same \"random\"
--- values).  Some form of mutable state must be used, such as an 'IORef',
--- 'State' monad, etc..  A few default instances are provided by this module
--- along with more-general functions ('getRandomPrimFromMTRef' and
--- 'getRandomPrimFromMTState') usable as implementations for new cases
--- users might need.
-module Data.Random.Source.PureMT 
-    ( PureMT, newPureMT, pureMT
-    , module Data.Random.Source.PureMT 
-    ) where
-
-import Data.Random.Internal.Primitives
-import Data.Random.Source
-import System.Random.Mersenne.Pure64
-
-import Data.StateRef
-
-import Control.Monad.State
-import qualified Control.Monad.ST.Strict as S
-import qualified Control.Monad.State.Strict as S
-
--- |Given a function for applying a 'PureMT' transformation to some hidden 
--- state, this function derives a function able to generate all 'Prim's
--- in the given monad.  This is then suitable for either a 'MonadRandom' or
--- 'RandomSource' instance, where the 'supportedPrims' or
--- 'supportedPrimsFrom' function (respectively) is @const True@.
-{-# INLINE getRandomPrimBy #-}
-getRandomPrimBy :: Monad m => (forall t. (PureMT -> (t, PureMT)) -> m t) -> Prim a -> m a
-getRandomPrimBy getThing = getPrimWhere supported (\prim -> getThing (genPrim prim))
-    where 
-        {-# INLINE supported #-}
-        supported :: Prim a -> Bool
-        supported PrimWord64 = True
-        supported PrimDouble = True
-        supported _          = False
-        
-        {-# INLINE genPrim #-}
-        genPrim :: Prim a -> (PureMT -> (a, PureMT))
-        genPrim PrimWord64 = randomWord64
-        genPrim PrimDouble = randomDouble
-        genPrim p = error ("getRandomPrimBy: genPrim called for unsupported prim " ++ show p)
-
--- |Given a mutable reference to a 'PureMT' generator, we can implement
--- 'RandomSource' for in any monad in which the reference can be modified.
--- 
--- Typically this would be used to define a new 'RandomSource' instance for
--- some new reference type or new monad in which an existing reference type
--- can be modified atomically.  As an example, the following instance could
--- be used to describe how 'IORef' 'PureMT' can be a 'RandomSource' in the
--- 'IO' monad:
--- 
--- > instance RandomSource IO (IORef PureMT) where
--- >     supportedPrimsFrom _ _ = True
--- >     getSupportedRandomPrimFrom = getRandomPrimFromMTRef
--- 
--- (note that there is actually a more general instance declared already
--- covering this as a a special case, so there's no need to repeat this
--- declaration anywhere)
--- 
--- Example usage:
--- 
--- > main = do
--- >     src <- newIORef (pureMT 1234)          -- OR: newPureMT >>= newIORef
--- >     x <- sampleFrom src (uniform 0 100)    -- OR: runRVar (uniform 0 100) src
--- >     print x
-getRandomPrimFromMTRef ::
-    forall sr m t.
-    (Monad m, ModifyRef sr m PureMT) => sr -> Prim t -> m t
-getRandomPrimFromMTRef ref = getRandomPrimBy getThing
-    where
-        {-# INLINE getThing #-}
-        getThing :: forall a. (PureMT -> (a, PureMT)) -> m a
-        getThing thing = atomicModifyReference ref $ \(!oldMT) -> 
-            case thing oldMT of (!w, !newMT) -> (newMT, w)
-            
-
--- |Similarly, @getRandomPrimFromMTState x@ can be used in any \"state\"
--- monad in the mtl sense whose state is a 'PureMT' generator.
--- Additionally, the standard mtl state monads have 'MonadRandom' instances
--- which do precisely that, allowing an easy conversion of 'RVar's and
--- other 'Distribution' instances to \"pure\" random variables (e.g., by
--- @runState . sample :: Distribution d t => d t -> PureMT -> (t, PureMT)@.
--- 'PureMT' in the type there can be replaced by 'StdGen' or anything else 
--- satisfying @MonadRandom (State s) => s@).
--- 
--- For example, this module includes the following declaration:
--- 
--- > instance MonadRandom (State PureMT) where
--- >     supportedPrims _ _ = True
--- >     getSupportedRandomPrim = getRandomPrimFromMTState
--- 
--- This describes a \"standard\" way of getting random values in 'State'
--- 'PureMT', which can then be used in various ways, for example (assuming 
--- some 'RVar' @foo@ and some 'Word64' @seed@):
--- 
--- > runState (runRVar foo StdRandom) (pureMT seed)
--- > runState (sampleFrom StdRandom foo) (pureMT seed)
--- > runState (sample foo) (pureMT seed)
--- 
--- Of course, the initial 'PureMT' state could also be obtained by any other
--- convenient means, such as 'newPureMT' if you don't care what seed is used.
-getRandomPrimFromMTState :: 
-    forall m t.
-    MonadState PureMT m 
-    => Prim t -> m t
-getRandomPrimFromMTState = getRandomPrimBy getThing
-    where
-        {-# INLINE getThing #-}
-        getThing :: forall a. (PureMT -> (a, PureMT)) -> m a
-        getThing thing = do
-            !mt <- get
-            let (!ws, !newMt) = thing mt
-            put newMt
-            return ws
-
-#ifndef MTL2
-instance MonadRandom (State PureMT) where
-    getRandomPrim = getRandomPrimFromMTState
-
-instance MonadRandom (S.State PureMT) where
-    getRandomPrim = getRandomPrimFromMTState
-#endif
-
-instance (Monad m1, ModifyRef (Ref m2 PureMT) m1 PureMT) => RandomSource m1 (Ref m2 PureMT) where
-    getRandomPrimFrom = getRandomPrimFromMTRef
-    
-instance Monad m => MonadRandom (StateT PureMT m) where
-    getRandomPrim = getRandomPrimFromMTState
-
-instance Monad m => MonadRandom (S.StateT PureMT m) where
-    getRandomPrim = getRandomPrimFromMTState
-
-instance (Monad m, ModifyRef (IORef PureMT) m PureMT) => RandomSource m (IORef PureMT) where
-    {-# SPECIALIZE instance RandomSource IO (IORef PureMT) #-}
-    getRandomPrimFrom = getRandomPrimFromMTRef
-    
-instance (Monad m, ModifyRef (STRef s PureMT) m PureMT) => RandomSource m (STRef s PureMT) where
-    {-# SPECIALIZE instance RandomSource (ST s) (STRef s PureMT) #-}
-    {-# SPECIALIZE instance RandomSource (S.ST s) (STRef s PureMT) #-}
-    getRandomPrimFrom = getRandomPrimFromMTRef
-
--- Note that this instance is probably a Bad Idea.  STM allows random variables
--- to interact in spooky quantum-esque ways - One transaction can 'retry' until
--- it gets a \"random\" answer it likes, which causes it to selectively consume 
--- entropy, biasing the supply from which other random variables will draw.
--- instance (Monad m, ModifyRef (TVar PureMT) m PureMT) => RandomSource m (TVar PureMT) where
---     {-# SPECIALIZE instance RandomSource IO  (TVar PureMT) #-}
---     {-# SPECIALIZE instance RandomSource STM (TVar PureMT) #-}
---     getRandomPrimFrom = getRandomPrimFromMTRef
-    
diff --git a/src/Data/Random/Source/Std.hs b/src/Data/Random/Source/Std.hs
deleted file mode 100644
--- a/src/Data/Random/Source/Std.hs
+++ /dev/null
@@ -1,20 +0,0 @@
-{-
- -      ``Data/Random/Source/Std''
- -}
-{-# LANGUAGE
-    MultiParamTypeClasses, FlexibleInstances
-  #-}
-
-module Data.Random.Source.Std where
-
-import Data.Random.Source
-
--- |A token representing the \"standard\" entropy source in a 'MonadRandom'
--- monad.  Its sole purpose is to make the following true (when the types check):
---
--- > sampleFrom StdRandom === sample
-data StdRandom = StdRandom
-
-instance MonadRandom m => RandomSource m StdRandom where
-    {-SPECIALIZE instance MonadRandom m => RandomSource m StdRandom -}
-    getRandomPrimFrom StdRandom = getRandomPrim
diff --git a/src/Data/Random/Source/StdGen.hs b/src/Data/Random/Source/StdGen.hs
deleted file mode 100644
--- a/src/Data/Random/Source/StdGen.hs
+++ /dev/null
@@ -1,188 +0,0 @@
-{-# LANGUAGE
-    CPP,
-    MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, GADTs,
-    BangPatterns, RankNTypes,
-    ScopedTypeVariables
-  #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-
--- |This module provides functions useful for implementing new 'MonadRandom'
--- and 'RandomSource' instances for state-abstractions containing 'StdGen'
--- values (the pure pseudorandom generator provided by the System.Random
--- module in the \"random\" package), as well as instances for some common
--- cases.
-module Data.Random.Source.StdGen where
-
-import Data.Random.Internal.Words
-import Data.Random.Internal.Primitives
-import Data.Random.Source
-import System.Random
-import Control.Monad.Prompt
-import Control.Monad.State
-import qualified Control.Monad.ST.Strict as S
-import qualified Control.Monad.State.Strict as S
-import Data.StateRef
-import Data.Word
-
-
-instance (Monad m1, ModifyRef (Ref m2 StdGen) m1 StdGen) => RandomSource m1 (Ref m2 StdGen) where
-    getRandomPrimFrom = getRandomPrimFromRandomGenRef
-
-instance (Monad m, ModifyRef (IORef   StdGen) m StdGen) => RandomSource m (IORef   StdGen) where
-    {-# SPECIALIZE instance RandomSource IO (IORef StdGen) #-}
-    getRandomPrimFrom = getRandomPrimFromRandomGenRef
-
--- Note that this instance is probably a Bad Idea.  STM allows random variables
--- to interact in spooky quantum-esque ways - One transaction can 'retry' until
--- it gets a \"random\" answer it likes, which causes it to selectively consume 
--- entropy, biasing the supply from which other random variables will draw.
--- instance (Monad m, ModifyRef (TVar    StdGen) m StdGen) => RandomSource m (TVar    StdGen) where
---     {-# SPECIALIZE instance RandomSource IO  (TVar StdGen) #-}
---     {-# SPECIALIZE instance RandomSource STM (TVar StdGen) #-}
---     supportedPrimsFrom _ _ = True
---     getSupportedRandomPrimFrom = getRandomPrimFromRandomGenRef
-
-instance (Monad m, ModifyRef (STRef s StdGen) m StdGen) => RandomSource m (STRef s StdGen) where
-    {-# SPECIALIZE instance RandomSource (ST s) (STRef s StdGen) #-}
-    {-# SPECIALIZE instance RandomSource (S.ST s) (STRef s StdGen) #-}
-    getRandomPrimFrom = getRandomPrimFromRandomGenRef
-
-getRandomPrimFromStdGenIO :: Prim a -> IO a
-getRandomPrimFromStdGenIO prim
-    | supported prim = genPrim prim
-    | otherwise = runPromptM getRandomPrimFromStdGenIO (decomposePrimWhere supported prim)
-    where 
-        {-# INLINE supported #-}
-        supported :: Prim a -> Bool
-        supported PrimWord8             = True
-        supported PrimWord16            = True
-        supported PrimWord32            = True
-        supported PrimWord64            = True
-        supported PrimDouble            = True
-        supported (PrimNByteInteger _)  = True
-        supported _                     = False
-        
-        -- based on reading the source of the "random" library's implementation, I do
-        -- not believe that the randomRIO (0,1) implementation for Double is capable of producing
-        -- the value 0.  Therefore, I'm not using it.  If this is an incorrect reading on
-        -- my part, or if this changes, then feel free to change the implementation.
-        -- Same goes for the other getRandomDouble... functions here.
-
-        {-# INLINE genPrim #-}
-        genPrim :: Prim a -> IO a
-        genPrim PrimWord8            = fmap fromIntegral                  (randomRIO (0, 0xff) :: IO Int)
-        genPrim PrimWord16           = fmap fromIntegral                  (randomRIO (0, 0xffff) :: IO Int)
-        genPrim PrimWord32           = fmap fromInteger                   (randomRIO (0, 0xffffffff))
-        genPrim PrimWord64           = fmap fromInteger                   (randomRIO (0, 0xffffffffffffffff))
-        genPrim PrimDouble           = fmap (wordToDouble . fromInteger)  (randomRIO (0, 0xffffffffffffffff))
-        genPrim (PrimNByteInteger n) = randomRIO (0, iterate (*256) 1 !! n)
-        genPrim p = error ("getRandomPrimFromStdGenIO: genPrim called for unsupported prim " ++ show p)
-
--- |Given a mutable reference to a 'RandomGen' generator, we can make a
--- 'RandomSource' usable in any monad in which the reference can be modified.
--- 
--- See "Data.Random.Source.PureMT".'getRandomPrimFromMTRef' for more detailed
--- usage hints - this function serves exactly the same purpose except for a
--- 'StdGen' generator instead of a 'PureMT' generator.
-getRandomPrimFromRandomGenRef :: 
-    forall sr m g t.
-    (Monad m, ModifyRef sr m g, RandomGen g) =>
-    sr -> Prim t -> m t
-getRandomPrimFromRandomGenRef ref prim
-    | supported prim = genPrim prim getThing
-    | otherwise = runPromptM (getRandomPrimFromRandomGenRef ref) (decomposePrimWhere supported prim)
-    where 
-        {-# INLINE supported #-}
-        supported :: forall a. Prim a -> Bool
-        supported PrimWord8             = True
-        supported PrimWord16            = True
-        supported PrimWord32            = True
-        supported PrimWord64            = True
-        supported PrimDouble            = True
-        supported (PrimNByteInteger _)  = True
-        supported _                     = False
-        
-        {-# INLINE genPrim #-}
-        genPrim :: forall a c g. (RandomGen g) => Prim a -> (forall b. (g -> (b, g)) -> (b -> a) -> c) -> c
-        genPrim PrimWord8            f = f (randomR (0, 0xff))                (fromIntegral :: Int -> Word8)
-        genPrim PrimWord16           f = f (randomR (0, 0xffff))              (fromIntegral :: Int -> Word16)
-        genPrim PrimWord32           f = f (randomR (0, 0xffffffff))          (fromInteger)
-        genPrim PrimWord64           f = f (randomR (0, 0xffffffffffffffff))  (fromInteger)
-        genPrim PrimDouble           f = f (randomR (0, 0x000fffffffffffff))  (flip encodeFloat (-52))
-        genPrim (PrimNByteInteger n) f = f (randomR (0, iterate (*256) 1 !! n)) (id :: Integer -> Integer)
-        genPrim p _ = error ("getRandomPrimFromRandomGenRef: genPrim called for unsupported prim " ++ show p)
-        
-        {-# INLINE getThing #-}
-        getThing :: forall a b. (g -> (a, g)) -> (a -> b) -> m b
-        getThing thing f = atomicModifyReference ref $ \(!oldMT) -> case thing oldMT of (!w, !newMT) -> (newMT, f w)
-
-
--- |Similarly, @getRandomWordFromRandomGenState x@ can be used in any \"state\"
--- monad in the mtl sense whose state is a 'RandomGen' generator.
--- Additionally, the standard mtl state monads have 'MonadRandom' instances
--- which do precisely that, allowing an easy conversion of 'RVar's and
--- other 'Distribution' instances to \"pure\" random variables.
--- 
--- Again, see "Data.Random.Source.PureMT".'getRandomPrimFromMTState' for more
--- detailed usage hints - this function serves exactly the same purpose except 
--- for a 'StdGen' generator instead of a 'PureMT' generator.
-{-# SPECIALIZE getRandomPrimFromRandomGenState :: Prim a -> State StdGen a #-}
-{-# SPECIALIZE getRandomPrimFromRandomGenState :: Monad m => Prim a -> StateT StdGen m a #-}
-getRandomPrimFromRandomGenState :: 
-    forall g m t.
-    (RandomGen g, MonadState g m) 
-    => Prim t -> m t
-getRandomPrimFromRandomGenState prim
-    = runPromptM genSupported (decomposePrimWhere supported prim)
-    where 
-        {-# INLINE genSupported #-}
-        genSupported :: forall a. Prim a -> m a
-        genSupported prim = genPrim prim getThing
-        
-        {-# INLINE supported #-}
-        supported :: Prim a -> Bool
-        supported PrimWord8             = True
-        supported PrimWord16            = True
-        supported PrimWord32            = True
-        supported PrimWord64            = True
-        supported PrimDouble            = True
-        supported (PrimNByteInteger _)  = True
-        supported _                     = False
-        
-        {-# INLINE genPrim #-}
-        genPrim :: Prim a -> (forall b. (g -> (b, g)) -> (b -> a) -> c) -> c
-        genPrim PrimWord8            f = f (randomR (0, 0xff))                (fromIntegral :: Int -> Word8)
-        genPrim PrimWord16           f = f (randomR (0, 0xffff))              (fromIntegral :: Int -> Word16)
-        genPrim PrimWord32           f = f (randomR (0, 0xffffffff))          (fromInteger)
-        genPrim PrimWord64           f = f (randomR (0, 0xffffffffffffffff))  (fromInteger)
-        genPrim PrimDouble           f = f (randomR (0, 0x000fffffffffffff))  (flip encodeFloat (-52))
-          {- not using the Random Double instance for 2 reasons.  1st, it only generates 32 bits of entropy, when 
-             a [0,1) Double has room for 52.  Second, it appears there's a bug where it can actually generate a 
-             negative number in the case where randomIvalInteger returns minBound::Int32. -}
---        genPrim PrimDouble f = f (randomR (0, 1.0))  (id)
-        genPrim (PrimNByteInteger n) f = f (randomR (0, iterate (*256) 1 !! n)) id
-        genPrim p _ = error ("getRandomPrimFromRandomGenState: genPrim called for unsupported prim " ++ show p)
-        
-        {-# INLINE getThing #-}
-        getThing :: forall a b. (g -> (a, g)) -> (a -> b) -> m b
-        getThing thing f = do
-            !oldGen <- get
-            case thing oldGen of
-                (!i,!newGen) -> do
-                    put newGen
-                    return (f $! i)
-
-#ifndef MTL2
-instance MonadRandom (State StdGen) where
-    getRandomPrim = getRandomPrimFromRandomGenState
-
-instance MonadRandom (S.State StdGen) where
-    getRandomPrim = getRandomPrimFromRandomGenState
-#endif
-
-instance Monad m => MonadRandom (StateT StdGen m) where
-    getRandomPrim = getRandomPrimFromRandomGenState
-
-instance Monad m => MonadRandom (S.StateT StdGen m) where
-    getRandomPrim = getRandomPrimFromRandomGenState
-
