module System.Random.MWC.Monad (
Rand
, toRand
, RandIO
, asRandIO
, RandST
, asRandST
, runRand
, runWithCreate
, runWithSeed
, runWithVector
, runWithSystemRandom
, uniform
, uniformR
, Seed
, toSeed
, fromSeed
, save
) where
import Control.Applicative
import Control.Monad (ap)
import Control.Monad.Trans.Class (MonadTrans(..))
import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad.ST (ST)
import Control.Monad.Primitive (PrimMonad, PrimState)
import Control.Monad.Primitive.Class (MonadPrim(..))
import Data.Word (Word32)
import qualified Data.Vector.Generic as G
import qualified System.Random.MWC as MWC
import System.Random.MWC (Gen,Variate,Seed,toSeed,fromSeed)
newtype Rand m a = Rand {
runRand :: Gen (PrimState (BasePrimMonad m)) -> m a
}
instance (Monad m) => Functor (Rand m) where
fmap f (Rand rnd) = Rand $ \g -> (return . f) =<< (rnd g)
instance (Monad m) => Monad (Rand m) where
return = Rand . const . return
(Rand rnd) >>= f = Rand $ \g -> (\x -> runRand (f x) g) =<< rnd g
instance (Monad m) => Applicative (Rand m) where
pure = return
(<*>) = ap
instance MonadTrans Rand where
lift = Rand . const
instance MonadIO m => MonadIO (Rand m) where
liftIO = lift . liftIO
instance MonadPrim m => MonadPrim (Rand m) where
type BasePrimMonad (Rand m) = BasePrimMonad m
liftPrim = lift . liftPrim
type RandST s a = Rand (ST s) a
asRandST :: RandST s a -> RandST s a
asRandST = id
type RandIO a = Rand IO a
asRandIO :: RandIO a -> RandIO a
asRandIO = id
runWithCreate :: MonadPrim m => Rand m a -> m a
runWithCreate m = runRand m =<< liftPrim MWC.create
runWithVector :: (G.Vector v Word32, MonadPrim m) => Rand m a -> v Word32 -> m a
runWithVector m v = runRand m =<< liftPrim (MWC.initialize v)
runWithSeed :: MonadPrim m => Seed -> Rand m a -> m a
runWithSeed seed m = runRand m =<< liftPrim (MWC.restore seed)
runWithSystemRandom :: (MonadPrim m, BasePrimMonad m ~ m) => Rand m a -> IO a
runWithSystemRandom = MWC.withSystemRandom . runRand
toRand :: MonadPrim m => (Gen (PrimState (BasePrimMonad m)) -> BasePrimMonad m a) -> Rand m a
toRand generator = Rand $ \g -> liftPrim (generator g)
uniform :: (MonadPrim m, Variate a) => Rand m a
uniform = toRand $ \g -> MWC.uniform g
uniformR :: (MonadPrim m, Variate a) => (a,a) -> Rand m a
uniformR rng = toRand $ \g -> MWC.uniformR rng g
save :: MonadPrim m => Rand m Seed
save = Rand $ liftPrim . MWC.save