-- | Randomized values module Numeric.Probability.Random where import qualified Numeric.Probability.Distribution as Dist import qualified Numeric.Probability.Transition as Trans import qualified System.Random as Random import System.Random (Random, ) import Control.Applicative (Applicative(..)) import Control.Monad.Trans.State (State, state, evalState, runState, ) import qualified System.IO as IO import Prelude hiding (print) -- * random generator -- | Random values newtype T a = Cons {decons :: State Random.StdGen a} instance Monad T where return x = Cons (return x) Cons x >>= y = Cons (decons . y =<< x) instance Functor T where fmap f = Cons . fmap f . decons instance Applicative T where pure x = Cons (pure x) fm <*> m = Cons (decons fm <*> decons m) randomR :: Random.Random a => (a, a) -> T a randomR rng = Cons (state (Random.randomR rng)) {- | Run random action in 'IO' monad. -} run :: T a -> IO a run = Random.getStdRandom . runState . decons {- | Run random action without 'IO' using a seed. -} runSeed :: Random.StdGen -> T a -> a runSeed g r = evalState (decons r) g print :: Show a => T a -> IO () print r = IO.print =<< run r -- instance Show (IO a) where -- show _ = "" pick :: (Num prob, Ord prob, Random prob) => Dist.T prob a -> T a pick d = return . Dist.selectP d =<< randomR (0,1) -- * random distribution -- | Randomized distribution type Distribution prob a = T (Dist.T prob a) above, below :: (Num prob, Ord prob, Ord a) => prob -> Distribution prob a -> Distribution prob (Dist.Select a) above p = fmap (Dist.above p) below p = fmap (Dist.below p) {- | 'dist' converts a list of randomly generated values into a distribution by taking equal weights for all values. Thus @dist (replicate n rnd)@ simulates @rnd@ @n@ times and returns an estimation of the distribution represented by @rnd@. -} dist :: (Fractional prob, Ord a) => [T a] -> Distribution prob a dist = fmap (Dist.norm . Dist.uniform) . sequence -- * Randomized changes -- | random change type Change a = a -> T a change :: (Num prob, Ord prob, Random prob) => Trans.T prob a -> Change a change t = pick . t -- * Randomized transitions -- | random transition type Transition prob a = a -> Distribution prob a type ApproxDist a = T [a] {- for quickCheck LAWS const . pick = random . const -}