{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
module Control.Monad.LazyRandom
(
module System.Random,
module Control.Monad.LazyRandom.Class,
evalRand,
runRand,
evalRandIO,
-- fromList,
Rand -- but not the data constructors
)
where
import Control.Monad.LazyRandom.Class
--------------------------------------------------------------------------
-- imports
import System.Random
( Random(..)
, RandomGen(..)
, StdGen, mkStdGen, getStdRandom
)
import Control.Monad
( liftM
, ap
)
import Control.Applicative
( Applicative(..)
)
--------------------------------------------------------------------------
-- ** Based on quickcheck generator type
newtype Rand r a = MkRand{ unRand :: r -> a }
instance Functor (Rand r) where
fmap f (MkRand h) = MkRand (f . h)
instance RandomGen r => Applicative (Rand r) where
pure = return
(<*>) = ap
instance RandomGen r => Monad (Rand r) where
return x = MkRand (const x)
MkRand m >>= k =
MkRand (\r ->
let (r1,r2) = split r
MkRand m' = k (m r1)
in m' r2
)
-- | Evaluate a random computation using the generator @g@. Note that the
-- generator @g@ is not returned, so there's no way to recover the
-- updated version of @g@.
evalRand :: (RandomGen g) => Rand g a -> g -> a
evalRand (MkRand f) g = f g
-- | Run a random computation using the generator @g@, returning the result
-- and the updated generator.
runRand :: (RandomGen g) => Rand g a -> g -> (a, g)
runRand (MkRand f) g = (f g1, g2)
where (g1, g2) = split g
-- | Evaluate a random computation in the IO monad, using the random number
-- generator supplied by 'System.Random.getStdRandom'.
evalRandIO :: Rand StdGen a -> IO a
evalRandIO m = getStdRandom (runRand m)
instance (RandomGen g) => MonadRandom (Rand g) where
getRandom = MkRand $ fst . random
getRandoms = MkRand $ randoms
getRandomR range = MkRand $ fst . randomR range
getRandomRs range = MkRand $ randoms
instance (RandomGen g) => MonadSplit g (Rand g) where
getSplit = MkRand id -- I think this has to be right ---NR
--------------------------------------------------------------------------
-- the end.