-- | In this module, 'MSF's in a monad supporting random number generation
--   (i.e. having the 'RandT' layer in its stack) can be run.
--   Running means supplying an initial random number generator,
--   where the update of the generator at every random number generation
--   is already taken care of.
--
--   Under the hood, 'RandT' is basically just 'StateT',
--   with the current random number generator as mutable state.

module Control.Monad.Trans.MSF.Random
  (
    runRandS
  , evalRandS

  , getRandomS
  , getRandomsS
  , getRandomRS
  , getRandomRS_
  , getRandomsRS
  , getRandomsRS_
  ) where

-- External
import Control.Monad.Random

-- Internal
import Data.MonadicStreamFunction
import Control.Monad.Trans.MSF.State

-- | Run an 'MSF' in the 'RandT' random number monad transformer
--   by supplying an initial random generator.
--   Updates the generator every step.
runRandS :: (RandomGen g, Functor m, Monad m)
         => MSF (RandT g m) a b
         -> g -- ^ The initial random number generator.
         -> MSF m a (g, b)
runRandS :: MSF (RandT g m) a b -> g -> MSF m a (g, b)
runRandS = MSF (StateT g m) a b -> g -> MSF m a (g, b)
forall (m :: * -> *) s a b.
(Functor m, Monad m) =>
MSF (StateT s m) a b -> s -> MSF m a (s, b)
runStateS_ (MSF (StateT g m) a b -> g -> MSF m a (g, b))
-> (MSF (RandT g m) a b -> MSF (StateT g m) a b)
-> MSF (RandT g m) a b
-> g
-> MSF m a (g, b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall c. RandT g m c -> StateT g m c)
-> MSF (RandT g m) a b -> MSF (StateT g m) a b
forall (m2 :: * -> *) (m1 :: * -> *) a b.
(Monad m2, Monad m1) =>
(forall c. m1 c -> m2 c) -> MSF m1 a b -> MSF m2 a b
morphS ((g -> m (c, g)) -> StateT g m c
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateT ((g -> m (c, g)) -> StateT g m c)
-> (RandT g m c -> g -> m (c, g)) -> RandT g m c -> StateT g m c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RandT g m c -> g -> m (c, g)
forall g (m :: * -> *) a. RandT g m a -> g -> m (a, g)
runRandT)

-- | Evaluate an 'MSF' in the 'RandT' transformer,
--   i.e. extract possibly random values
--   by supplying an initial random generator.
--   Updates the generator every step but discharges the generator.
evalRandS :: (RandomGen g, Functor m, Monad m)
          => MSF (RandT g m) a b -> g -> MSF m a b
evalRandS :: MSF (RandT g m) a b -> g -> MSF m a b
evalRandS MSF (RandT g m) a b
msf g
g = MSF (RandT g m) a b -> g -> MSF m a (g, b)
forall g (m :: * -> *) a b.
(RandomGen g, Functor m, Monad m) =>
MSF (RandT g m) a b -> g -> MSF m a (g, b)
runRandS MSF (RandT g m) a b
msf g
g MSF m a (g, b) -> MSF m (g, b) b -> MSF m a b
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> ((g, b) -> b) -> MSF m (g, b) b
forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr (g, b) -> b
forall a b. (a, b) -> b
snd

-- | Create a stream of random values.
getRandomS :: (MonadRandom m, Random b) => MSF m a b
getRandomS :: MSF m a b
getRandomS = m b -> MSF m a b
forall (m :: * -> *) b a. Monad m => m b -> MSF m a b
constM m b
forall (m :: * -> *) a. (MonadRandom m, Random a) => m a
getRandom


-- | Create a stream of lists of random values.
getRandomsS :: (MonadRandom m, Random b) => MSF m a [b]
getRandomsS :: MSF m a [b]
getRandomsS = m [b] -> MSF m a [b]
forall (m :: * -> *) b a. Monad m => m b -> MSF m a b
constM m [b]
forall (m :: * -> *) a. (MonadRandom m, Random a) => m [a]
getRandoms

-- | Create a stream of random values in a given fixed range.
getRandomRS :: (MonadRandom m, Random b) => (b, b) -> MSF m a b
getRandomRS :: (b, b) -> MSF m a b
getRandomRS (b, b)
range = m b -> MSF m a b
forall (m :: * -> *) b a. Monad m => m b -> MSF m a b
constM (m b -> MSF m a b) -> m b -> MSF m a b
forall a b. (a -> b) -> a -> b
$ (b, b) -> m b
forall (m :: * -> *) a. (MonadRandom m, Random a) => (a, a) -> m a
getRandomR (b, b)
range

-- | Create a stream of random values in a given range,
--   where the range is specified on every tick.
getRandomRS_ :: (MonadRandom m, Random b) => MSF m (b, b) b
getRandomRS_ :: MSF m (b, b) b
getRandomRS_  = ((b, b) -> m b) -> MSF m (b, b) b
forall (m :: * -> *) a b. Monad m => (a -> m b) -> MSF m a b
arrM (b, b) -> m b
forall (m :: * -> *) a. (MonadRandom m, Random a) => (a, a) -> m a
getRandomR

-- | Create a stream of lists of random values in a given fixed range.
getRandomsRS :: (MonadRandom m, Random b) => (b, b) -> MSF m a [b]
getRandomsRS :: (b, b) -> MSF m a [b]
getRandomsRS (b, b)
range = m [b] -> MSF m a [b]
forall (m :: * -> *) b a. Monad m => m b -> MSF m a b
constM (m [b] -> MSF m a [b]) -> m [b] -> MSF m a [b]
forall a b. (a -> b) -> a -> b
$ (b, b) -> m [b]
forall (m :: * -> *) a.
(MonadRandom m, Random a) =>
(a, a) -> m [a]
getRandomRs (b, b)
range

-- | Create a stream of lists of random values in a given range,
--   where the range is specified on every tick.
getRandomsRS_ :: (MonadRandom m, Random b) => MSF m (b, b) [b]
getRandomsRS_ :: MSF m (b, b) [b]
getRandomsRS_ = ((b, b) -> m [b]) -> MSF m (b, b) [b]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> MSF m a b
arrM (b, b) -> m [b]
forall (m :: * -> *) a.
(MonadRandom m, Random a) =>
(a, a) -> m [a]
getRandomRs