module Rand ( initRand, withStdGen, randM, randGen, random, randomR, randFrom, ) where import System.Random import Control.Applicative import Control.Monad.State.Strict import Prelude import Types initRand :: (Maybe String) -> IO Rand initRand Nothing = DefRand <$> getStdGen initRand (Just "0") = return NoRand initRand (Just n) = return $ Rand $ mkStdGen $ read n withStdGen :: Rand -> a -> (StdGen -> a) -> a withStdGen NoRand d _ = d withStdGen (Rand r) _ f = f r withStdGen (DefRand r) _ f = f r randGen :: Rand -> StdGen randGen = fst . randGen' randGen' :: Rand -> (StdGen, StdGen -> Rand) randGen' (Rand v) = (v, Rand) randGen' (DefRand v) = (v, DefRand) randGen' NoRand = (mkStdGen 0, \_ -> NoRand) randM :: (StdGen -> (v, StdGen)) -> M v randM f = do r <- gets randSource let (g, mk) = randGen' r let (v, g') = f g modify $ \s -> s { randSource = mk g' } return v randFrom :: [a] -> M a randFrom l = do n <- randM $ randomR (0,length l - 1) return (l !! n)