1. {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
  2.  
  3. module Control.Monad.LazyRandom
  4.   (
  5.     module System.Random,
  6.     module Control.Monad.LazyRandom.Class,
  7.     evalRand,
  8.     runRand,
  9.     evalRandIO,
  10. --    fromList,
  11.     Rand -- but not the data constructors
  12.     )
  13. where
  14.  
  15. import Control.Monad.LazyRandom.Class
  16.  
  17. --------------------------------------------------------------------------
  18. -- imports
  19.  
  20. import System.Random
  21.   ( Random(..)
  22.   , RandomGen(..)
  23.   , StdGen, mkStdGen, getStdRandom
  24.   )
  25.  
  26. import Control.Monad
  27.   ( liftM
  28.   , ap
  29.   )
  30.  
  31. import Control.Applicative
  32.   ( Applicative(..)
  33.   )
  34.  
  35. --------------------------------------------------------------------------
  36. -- ** Based on quickcheck generator type
  37.  
  38. newtype Rand r a = MkRand{ unRand :: r -> a }
  39.  
  40. instance Functor (Rand r) where
  41.   fmap f (MkRand h) = MkRand (f . h)
  42.  
  43. instance RandomGen r => Applicative (Rand r) where
  44.   pure  = return
  45.   (<*>) = ap
  46.  
  47. instance RandomGen r => Monad (Rand r) where
  48.   return x = MkRand (const x)
  49.  
  50.   MkRand m >>= k =
  51.     MkRand (\r ->
  52.       let (r1,r2)  = split r
  53.           MkRand m' = k (m r1)
  54.       in m' r2
  55.     )
  56.  
  57.  
  58.  
  59. -- | Evaluate a random computation using the generator @g@.  Note that the
  60. -- generator @g@ is not returned, so there's no way to recover the
  61. -- updated version of @g@.
  62. evalRand :: (RandomGen g) => Rand g a -> g -> a
  63. evalRand (MkRand f) g = f g
  64.  
  65. -- | Run a random computation using the generator @g@, returning the result
  66. -- and the updated generator.
  67. runRand :: (RandomGen g) => Rand g a -> g -> (a, g)
  68. runRand (MkRand f) g = (f g1, g2)
  69.   where (g1, g2) = split g
  70.  
  71. -- | Evaluate a random computation in the IO monad, using the random number
  72. -- generator supplied by 'System.Random.getStdRandom'.
  73. evalRandIO :: Rand StdGen a -> IO a
  74. evalRandIO m = getStdRandom (runRand m)
  75.  
  76.  
  77.  
  78. instance (RandomGen g) => MonadRandom (Rand g) where
  79.     getRandom = MkRand $ fst . random
  80.     getRandoms = MkRand $ randoms
  81.     getRandomR range = MkRand $ fst . randomR range
  82.     getRandomRs range = MkRand $ randoms
  83.  
  84. instance (RandomGen g) => MonadSplit g (Rand g) where
  85.     getSplit = MkRand id  -- I think this has to be right ---NR
  86.  
  87. --------------------------------------------------------------------------
  88. -- the end.