module AI.MEP.Random ( -- * Utilities drawFrom , double_ , uniformIn_ , withProbability , runRandIO -- * Re-exports from Math.Probable.Random , RandT , double , vectorOf , vectorOfVariate , uniformIn -- * Re-exports from System.Random.MWC , Variate ) where import Math.Probable.Random import System.Random.MWC ( Variate ) import Control.Monad.Primitive ( PrimMonad ) import Data.Vector as V runRandIO :: RandT IO a -> IO a runRandIO = mwc -- | Randomly draw an element from a vector drawFrom :: PrimMonad m => Vector a -> RandT m a drawFrom vec = do n <- uniformIn (0, V.length vec - 1) return $ vec V.! n -- | Similar to uniformIn, but using range -- @[a, b)@ instead of @[a, b]@ and only for integral types. uniformIn_ :: (PrimMonad m, Variate a, Integral a) => (a, a) -> RandT m a uniformIn_ (a, b) = uniformIn (a, b - 1) -- | Returns a double value from the range of @[0, 1)@. -- If there is no specific reason, then prefer double @(0, 1]@. double_ :: PrimMonad m => RandT m Double double_ = (subtract magicC) <$> double where -- Change the range (0, 1] to (0, 1]. -- http://hackage.haskell.org/package/mwc-random-0.13.6.0/docs/System-Random-MWC.html#v:uniform magicC = 2**(-53) -- | Modify a value with the probability @p@ withProbability :: PrimMonad m => Double -- ^ The probability @p@ -> (a -> RandT m a) -- ^ Modification function -> (a -> RandT m a) withProbability p modify x = do t <- double if t < p then modify x else return x