{-# LANGUAGE CPP                        #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE Trustworthy                #-}
{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE UndecidableInstances       #-}

{- |
Module       :  Control.Monad.Trans.Random.Strict
Copyright    :  (c) Brent Yorgey 2016
License      :  BSD3 (see LICENSE)

Maintainer   :  byorgey@gmail.com
Stability    :  experimental
Portability  :  non-portable (multi-param classes, functional dependencies, undecidable instances)

Strict random monads, passing a random number generator through a computation.
See below for examples.

In this version, sequencing of computations is strict (but computations are not
strict in the state unless you force it with seq or the like). For a lazy
version with the same interface, see "Control.Monad.Trans.Random.Lazy".
-}

module Control.Monad.Trans.Random.Strict
  ( -- * The Rand monad transformer
    Rand,
    liftRand,
    runRand,
    evalRand,
    execRand,
    mapRand,
    withRand,
    evalRandIO,
    -- * The RandT monad transformer
    RandT,
    liftRandT,
    runRandT,
    evalRandT,
    execRandT,
    mapRandT,
    withRandT,
    evalRandTIO,
    -- * Lifting other operations
    liftCallCC,
    liftCallCC',
    liftCatch,
    liftListen,
    liftPass,
    -- * StatefulGen interface
    RandGen(..),
    withRandGen,
    withRandGen_,
    -- * Examples
    -- ** Random monads
    -- $examples
  ) where

import           Control.Applicative
import           Control.Arrow                    (first)
import           Control.Monad
import           Control.Monad.Cont.Class
import           Control.Monad.Error.Class
import qualified Control.Monad.Fail               as Fail
import           Control.Monad.Fix
import           Control.Monad.IO.Class
import           Control.Monad.Primitive
import           Control.Monad.Random.Class
import           Control.Monad.RWS.Class
import           Control.Monad.Signatures
import           Control.Monad.Trans.Class
import qualified Control.Monad.Trans.State.Strict as StrictState
import           Data.Functor.Identity
#if MIN_VERSION_random(1,2,0)
import           System.Random.Stateful
#else
import           System.Random
#endif

-- | A random monad parameterized by the type @g@ of the generator to carry.
--
-- The 'return' function leaves the generator unchanged, while '>>=' uses the
-- final generator of the first computation as the initial generator of the
-- second.
type Rand g = RandT g Identity

-- | Construct a random monad computation from a function.
-- (The inverse of 'runRand'.)
liftRand
  :: (g -> (a, g))
  -- ^ pure random transformer
  -> Rand g a
  -- ^ equivalent generator-passing computation
liftRand :: (g -> (a, g)) -> Rand g a
liftRand = StateT g Identity a -> Rand g a
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g Identity a -> Rand g a)
-> ((g -> (a, g)) -> StateT g Identity a)
-> (g -> (a, g))
-> Rand g a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (g -> (a, g)) -> StateT g Identity a
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state

-- | Unwrap a random monad computation as a function.
-- (The inverse of 'liftRand'.)
runRand
  :: Rand g a
  -- ^ generator-passing computation to execute
  -> g
  -- ^ initial generator
  -> (a, g)
  -- ^ return value and final generator
runRand :: Rand g a -> g -> (a, g)
runRand Rand g a
t = Identity (a, g) -> (a, g)
forall a. Identity a -> a
runIdentity (Identity (a, g) -> (a, g))
-> (g -> Identity (a, g)) -> g -> (a, g)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rand g a -> g -> Identity (a, g)
forall g (m :: * -> *) a. RandT g m a -> g -> m (a, g)
runRandT Rand g a
t

-- | Evaluate a random computation with the given initial generator and return
-- the final value, discarding the final generator.
--
-- * @'evalRand' m s = fst ('runRand' m s)@
evalRand
  :: Rand g a
  -- ^ generator-passing computation to execute
  -> g
  -- ^ initial generator
  -> a
  -- ^ return value of the random computation
evalRand :: Rand g a -> g -> a
evalRand Rand g a
t = Identity a -> a
forall a. Identity a -> a
runIdentity (Identity a -> a) -> (g -> Identity a) -> g -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rand g a -> g -> Identity a
forall (m :: * -> *) g a. Monad m => RandT g m a -> g -> m a
evalRandT Rand g a
t

-- | Evaluate a random computation with the given initial generator and return
-- the final generator, discarding the final value.
--
-- * @'execRand' m s = snd ('runRand' m s)@
execRand
  :: Rand g a
  -- ^ generator-passing computation to execute
  -> g
  -- ^ initial generator
  -> g
  -- ^ final generator
execRand :: Rand g a -> g -> g
execRand Rand g a
t = Identity g -> g
forall a. Identity a -> a
runIdentity (Identity g -> g) -> (g -> Identity g) -> g -> g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rand g a -> g -> Identity g
forall (m :: * -> *) g a. Monad m => RandT g m a -> g -> m g
execRandT Rand g a
t

-- | Map both the return value and final generator of a computation using the
-- given function.
--
-- * @'runRand' ('mapRand' f m) = f . 'runRand' m@
mapRand :: ((a, g) -> (b, g)) -> Rand g a -> Rand g b
mapRand :: ((a, g) -> (b, g)) -> Rand g a -> Rand g b
mapRand (a, g) -> (b, g)
f = (Identity (a, g) -> Identity (b, g)) -> Rand g a -> Rand g b
forall (m :: * -> *) a g (n :: * -> *) b.
(m (a, g) -> n (b, g)) -> RandT g m a -> RandT g n b
mapRandT (((a, g) -> (b, g)) -> Identity (a, g) -> Identity (b, g)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (a, g) -> (b, g)
f)

-- | @'withRand' f m@ executes action @m@ on a generator modified by applying @f@.
--
-- * @'withRand' f m = 'modify' f >> m@
withRand :: (g -> g) -> Rand g a -> Rand g a
withRand :: (g -> g) -> Rand g a -> Rand g a
withRand = (g -> g) -> Rand g a -> Rand g a
forall g (m :: * -> *) a. (g -> g) -> RandT g m a -> RandT g m a
withRandT

-- | A random transformer monad parameterized by:
--
-- * @g@ - The generator.
--
-- * @m@ - The inner monad.
--
-- The 'return' function leaves the generator unchanged, while '>>=' uses the
-- final generator of the first computation as the initial generator of the
-- second.
newtype RandT g m a = RandT { RandT g m a -> StateT g m a
unRandT :: StrictState.StateT g m a }
  deriving (a -> RandT g m b -> RandT g m a
(a -> b) -> RandT g m a -> RandT g m b
(forall a b. (a -> b) -> RandT g m a -> RandT g m b)
-> (forall a b. a -> RandT g m b -> RandT g m a)
-> Functor (RandT g m)
forall a b. a -> RandT g m b -> RandT g m a
forall a b. (a -> b) -> RandT g m a -> RandT g m b
forall g (m :: * -> *) a b.
Functor m =>
a -> RandT g m b -> RandT g m a
forall g (m :: * -> *) a b.
Functor m =>
(a -> b) -> RandT g m a -> RandT g m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> RandT g m b -> RandT g m a
$c<$ :: forall g (m :: * -> *) a b.
Functor m =>
a -> RandT g m b -> RandT g m a
fmap :: (a -> b) -> RandT g m a -> RandT g m b
$cfmap :: forall g (m :: * -> *) a b.
Functor m =>
(a -> b) -> RandT g m a -> RandT g m b
Functor, Functor (RandT g m)
a -> RandT g m a
Functor (RandT g m)
-> (forall a. a -> RandT g m a)
-> (forall a b. RandT g m (a -> b) -> RandT g m a -> RandT g m b)
-> (forall a b c.
    (a -> b -> c) -> RandT g m a -> RandT g m b -> RandT g m c)
-> (forall a b. RandT g m a -> RandT g m b -> RandT g m b)
-> (forall a b. RandT g m a -> RandT g m b -> RandT g m a)
-> Applicative (RandT g m)
RandT g m a -> RandT g m b -> RandT g m b
RandT g m a -> RandT g m b -> RandT g m a
RandT g m (a -> b) -> RandT g m a -> RandT g m b
(a -> b -> c) -> RandT g m a -> RandT g m b -> RandT g m c
forall a. a -> RandT g m a
forall a b. RandT g m a -> RandT g m b -> RandT g m a
forall a b. RandT g m a -> RandT g m b -> RandT g m b
forall a b. RandT g m (a -> b) -> RandT g m a -> RandT g m b
forall a b c.
(a -> b -> c) -> RandT g m a -> RandT g m b -> RandT g m c
forall g (m :: * -> *). Monad m => Functor (RandT g m)
forall g (m :: * -> *) a. Monad m => a -> RandT g m a
forall g (m :: * -> *) a b.
Monad m =>
RandT g m a -> RandT g m b -> RandT g m a
forall g (m :: * -> *) a b.
Monad m =>
RandT g m a -> RandT g m b -> RandT g m b
forall g (m :: * -> *) a b.
Monad m =>
RandT g m (a -> b) -> RandT g m a -> RandT g m b
forall g (m :: * -> *) a b c.
Monad m =>
(a -> b -> c) -> RandT g m a -> RandT g m b -> RandT g m c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: RandT g m a -> RandT g m b -> RandT g m a
$c<* :: forall g (m :: * -> *) a b.
Monad m =>
RandT g m a -> RandT g m b -> RandT g m a
*> :: RandT g m a -> RandT g m b -> RandT g m b
$c*> :: forall g (m :: * -> *) a b.
Monad m =>
RandT g m a -> RandT g m b -> RandT g m b
liftA2 :: (a -> b -> c) -> RandT g m a -> RandT g m b -> RandT g m c
$cliftA2 :: forall g (m :: * -> *) a b c.
Monad m =>
(a -> b -> c) -> RandT g m a -> RandT g m b -> RandT g m c
<*> :: RandT g m (a -> b) -> RandT g m a -> RandT g m b
$c<*> :: forall g (m :: * -> *) a b.
Monad m =>
RandT g m (a -> b) -> RandT g m a -> RandT g m b
pure :: a -> RandT g m a
$cpure :: forall g (m :: * -> *) a. Monad m => a -> RandT g m a
$cp1Applicative :: forall g (m :: * -> *). Monad m => Functor (RandT g m)
Applicative, Applicative (RandT g m)
RandT g m a
Applicative (RandT g m)
-> (forall a. RandT g m a)
-> (forall a. RandT g m a -> RandT g m a -> RandT g m a)
-> (forall a. RandT g m a -> RandT g m [a])
-> (forall a. RandT g m a -> RandT g m [a])
-> Alternative (RandT g m)
RandT g m a -> RandT g m a -> RandT g m a
RandT g m a -> RandT g m [a]
RandT g m a -> RandT g m [a]
forall a. RandT g m a
forall a. RandT g m a -> RandT g m [a]
forall a. RandT g m a -> RandT g m a -> RandT g m a
forall g (m :: * -> *). MonadPlus m => Applicative (RandT g m)
forall g (m :: * -> *) a. MonadPlus m => RandT g m a
forall g (m :: * -> *) a.
MonadPlus m =>
RandT g m a -> RandT g m [a]
forall g (m :: * -> *) a.
MonadPlus m =>
RandT g m a -> RandT g m a -> RandT g m a
forall (f :: * -> *).
Applicative f
-> (forall a. f a)
-> (forall a. f a -> f a -> f a)
-> (forall a. f a -> f [a])
-> (forall a. f a -> f [a])
-> Alternative f
many :: RandT g m a -> RandT g m [a]
$cmany :: forall g (m :: * -> *) a.
MonadPlus m =>
RandT g m a -> RandT g m [a]
some :: RandT g m a -> RandT g m [a]
$csome :: forall g (m :: * -> *) a.
MonadPlus m =>
RandT g m a -> RandT g m [a]
<|> :: RandT g m a -> RandT g m a -> RandT g m a
$c<|> :: forall g (m :: * -> *) a.
MonadPlus m =>
RandT g m a -> RandT g m a -> RandT g m a
empty :: RandT g m a
$cempty :: forall g (m :: * -> *) a. MonadPlus m => RandT g m a
$cp1Alternative :: forall g (m :: * -> *). MonadPlus m => Applicative (RandT g m)
Alternative, Applicative (RandT g m)
a -> RandT g m a
Applicative (RandT g m)
-> (forall a b. RandT g m a -> (a -> RandT g m b) -> RandT g m b)
-> (forall a b. RandT g m a -> RandT g m b -> RandT g m b)
-> (forall a. a -> RandT g m a)
-> Monad (RandT g m)
RandT g m a -> (a -> RandT g m b) -> RandT g m b
RandT g m a -> RandT g m b -> RandT g m b
forall a. a -> RandT g m a
forall a b. RandT g m a -> RandT g m b -> RandT g m b
forall a b. RandT g m a -> (a -> RandT g m b) -> RandT g m b
forall g (m :: * -> *). Monad m => Applicative (RandT g m)
forall g (m :: * -> *) a. Monad m => a -> RandT g m a
forall g (m :: * -> *) a b.
Monad m =>
RandT g m a -> RandT g m b -> RandT g m b
forall g (m :: * -> *) a b.
Monad m =>
RandT g m a -> (a -> RandT g m b) -> RandT g m b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> RandT g m a
$creturn :: forall g (m :: * -> *) a. Monad m => a -> RandT g m a
>> :: RandT g m a -> RandT g m b -> RandT g m b
$c>> :: forall g (m :: * -> *) a b.
Monad m =>
RandT g m a -> RandT g m b -> RandT g m b
>>= :: RandT g m a -> (a -> RandT g m b) -> RandT g m b
$c>>= :: forall g (m :: * -> *) a b.
Monad m =>
RandT g m a -> (a -> RandT g m b) -> RandT g m b
$cp1Monad :: forall g (m :: * -> *). Monad m => Applicative (RandT g m)
Monad, Monad (RandT g m)
Alternative (RandT g m)
RandT g m a
Alternative (RandT g m)
-> Monad (RandT g m)
-> (forall a. RandT g m a)
-> (forall a. RandT g m a -> RandT g m a -> RandT g m a)
-> MonadPlus (RandT g m)
RandT g m a -> RandT g m a -> RandT g m a
forall a. RandT g m a
forall a. RandT g m a -> RandT g m a -> RandT g m a
forall g (m :: * -> *). MonadPlus m => Monad (RandT g m)
forall g (m :: * -> *). MonadPlus m => Alternative (RandT g m)
forall g (m :: * -> *) a. MonadPlus m => RandT g m a
forall g (m :: * -> *) a.
MonadPlus m =>
RandT g m a -> RandT g m a -> RandT g m a
forall (m :: * -> *).
Alternative m
-> Monad m
-> (forall a. m a)
-> (forall a. m a -> m a -> m a)
-> MonadPlus m
mplus :: RandT g m a -> RandT g m a -> RandT g m a
$cmplus :: forall g (m :: * -> *) a.
MonadPlus m =>
RandT g m a -> RandT g m a -> RandT g m a
mzero :: RandT g m a
$cmzero :: forall g (m :: * -> *) a. MonadPlus m => RandT g m a
$cp2MonadPlus :: forall g (m :: * -> *). MonadPlus m => Monad (RandT g m)
$cp1MonadPlus :: forall g (m :: * -> *). MonadPlus m => Alternative (RandT g m)
MonadPlus, m a -> RandT g m a
(forall (m :: * -> *) a. Monad m => m a -> RandT g m a)
-> MonadTrans (RandT g)
forall g (m :: * -> *) a. Monad m => m a -> RandT g m a
forall (m :: * -> *) a. Monad m => m a -> RandT g m a
forall (t :: (* -> *) -> * -> *).
(forall (m :: * -> *) a. Monad m => m a -> t m a) -> MonadTrans t
lift :: m a -> RandT g m a
$clift :: forall g (m :: * -> *) a. Monad m => m a -> RandT g m a
MonadTrans, Monad (RandT g m)
Monad (RandT g m)
-> (forall a. IO a -> RandT g m a) -> MonadIO (RandT g m)
IO a -> RandT g m a
forall a. IO a -> RandT g m a
forall g (m :: * -> *). MonadIO m => Monad (RandT g m)
forall g (m :: * -> *) a. MonadIO m => IO a -> RandT g m a
forall (m :: * -> *).
Monad m -> (forall a. IO a -> m a) -> MonadIO m
liftIO :: IO a -> RandT g m a
$cliftIO :: forall g (m :: * -> *) a. MonadIO m => IO a -> RandT g m a
$cp1MonadIO :: forall g (m :: * -> *). MonadIO m => Monad (RandT g m)
MonadIO, Monad (RandT g m)
Monad (RandT g m)
-> (forall a. (a -> RandT g m a) -> RandT g m a)
-> MonadFix (RandT g m)
(a -> RandT g m a) -> RandT g m a
forall a. (a -> RandT g m a) -> RandT g m a
forall g (m :: * -> *). MonadFix m => Monad (RandT g m)
forall g (m :: * -> *) a.
MonadFix m =>
(a -> RandT g m a) -> RandT g m a
forall (m :: * -> *).
Monad m -> (forall a. (a -> m a) -> m a) -> MonadFix m
mfix :: (a -> RandT g m a) -> RandT g m a
$cmfix :: forall g (m :: * -> *) a.
MonadFix m =>
(a -> RandT g m a) -> RandT g m a
$cp1MonadFix :: forall g (m :: * -> *). MonadFix m => Monad (RandT g m)
MonadFix, MonadReader r, MonadWriter w)

-- | Construct a random monad computation from an impure function.
-- (The inverse of 'runRandT'.)
liftRandT
  :: (g -> m (a, g))
  -- ^ impure random transformer
  -> RandT g m a
  -- ^ equivalent generator-passing computation
liftRandT :: (g -> m (a, g)) -> RandT g m a
liftRandT = StateT g m a -> RandT g m a
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m a -> RandT g m a)
-> ((g -> m (a, g)) -> StateT g m a)
-> (g -> m (a, g))
-> RandT g m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (g -> m (a, g)) -> StateT g m a
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StrictState.StateT

-- | Unwrap a random monad computation as an impure function.
-- (The inverse of 'liftRandT'.)
runRandT
  :: RandT g m a
  -- ^ generator-passing computation to execute
  -> g
  -- ^ initial generator
  -> m (a, g)
  -- ^ return value and final generator
runRandT :: RandT g m a -> g -> m (a, g)
runRandT = StateT g m a -> g -> m (a, g)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
StrictState.runStateT (StateT g m a -> g -> m (a, g))
-> (RandT g m a -> StateT g m a) -> RandT g m a -> g -> m (a, g)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RandT g m a -> StateT g m a
forall g (m :: * -> *) a. RandT g m a -> StateT g m a
unRandT

-- | Evaluate a random computation with the given initial generator and return
-- the final value, discarding the final generator.
--
-- * @'evalRandT' m g = liftM fst ('runRandT' m g)@
evalRandT :: (Monad m) => RandT g m a -> g -> m a
evalRandT :: RandT g m a -> g -> m a
evalRandT = StateT g m a -> g -> m a
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
StrictState.evalStateT (StateT g m a -> g -> m a)
-> (RandT g m a -> StateT g m a) -> RandT g m a -> g -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RandT g m a -> StateT g m a
forall g (m :: * -> *) a. RandT g m a -> StateT g m a
unRandT

-- | Evaluate a random computation with the given initial generator and return
-- the final generator, discarding the final value.
--
-- * @'execRandT' m g = liftM snd ('runRandT' m g)@
execRandT :: (Monad m) => RandT g m a -> g -> m g
execRandT :: RandT g m a -> g -> m g
execRandT = StateT g m a -> g -> m g
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m s
StrictState.execStateT (StateT g m a -> g -> m g)
-> (RandT g m a -> StateT g m a) -> RandT g m a -> g -> m g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RandT g m a -> StateT g m a
forall g (m :: * -> *) a. RandT g m a -> StateT g m a
unRandT

-- | Map both the return value and final generator of a computation using the
-- given function.
--
-- * @'runRandT' ('mapRandT' f m) = f . 'runRandT' m@
mapRandT :: (m (a, g) -> n (b, g)) -> RandT g m a -> RandT g n b
mapRandT :: (m (a, g) -> n (b, g)) -> RandT g m a -> RandT g n b
mapRandT m (a, g) -> n (b, g)
f = StateT g n b -> RandT g n b
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g n b -> RandT g n b)
-> (RandT g m a -> StateT g n b) -> RandT g m a -> RandT g n b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (m (a, g) -> n (b, g)) -> StateT g m a -> StateT g n b
forall (m :: * -> *) a s (n :: * -> *) b.
(m (a, s) -> n (b, s)) -> StateT s m a -> StateT s n b
StrictState.mapStateT m (a, g) -> n (b, g)
f (StateT g m a -> StateT g n b)
-> (RandT g m a -> StateT g m a) -> RandT g m a -> StateT g n b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RandT g m a -> StateT g m a
forall g (m :: * -> *) a. RandT g m a -> StateT g m a
unRandT

-- | @'withRandT' f m@ executes action @m@ on a generator modified by applying @f@.
--
-- * @'withRandT' f m = 'modify' f >> m@
withRandT :: (g -> g) -> RandT g m a -> RandT g m a
withRandT :: (g -> g) -> RandT g m a -> RandT g m a
withRandT g -> g
f = StateT g m a -> RandT g m a
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m a -> RandT g m a)
-> (RandT g m a -> StateT g m a) -> RandT g m a -> RandT g m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (g -> g) -> StateT g m a -> StateT g m a
forall s (m :: * -> *) a. (s -> s) -> StateT s m a -> StateT s m a
StrictState.withStateT g -> g
f (StateT g m a -> StateT g m a)
-> (RandT g m a -> StateT g m a) -> RandT g m a -> StateT g m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RandT g m a -> StateT g m a
forall g (m :: * -> *) a. RandT g m a -> StateT g m a
unRandT

instance (MonadCont m) => MonadCont (RandT g m) where
  callCC :: ((a -> RandT g m b) -> RandT g m a) -> RandT g m a
callCC = CallCC m (a, g) (b, g)
-> ((a -> RandT g m b) -> RandT g m a) -> RandT g m a
forall (m :: * -> *) a g b.
CallCC m (a, g) (b, g) -> CallCC (RandT g m) a b
liftCallCC' CallCC m (a, g) (b, g)
forall (m :: * -> *) a b. MonadCont m => ((a -> m b) -> m a) -> m a
callCC

instance (MonadError e m) => MonadError e (RandT g m) where
  throwError :: e -> RandT g m a
throwError = m a -> RandT g m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> RandT g m a) -> (e -> m a) -> e -> RandT g m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError
  catchError :: RandT g m a -> (e -> RandT g m a) -> RandT g m a
catchError = Catch e m (a, g)
-> RandT g m a -> (e -> RandT g m a) -> RandT g m a
forall e (m :: * -> *) a g.
Catch e m (a, g) -> Catch e (RandT g m) a
liftCatch Catch e m (a, g)
forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
catchError

instance (MonadReader r m, MonadWriter w m, MonadState s m) => MonadRWS r w s (RandT g m)

instance (RandomGen g, Monad m) => MonadRandom (RandT g m) where
  getRandomR :: (a, a) -> RandT g m a
getRandomR (a, a)
lohi = StateT g m a -> RandT g m a
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m a -> RandT g m a)
-> ((g -> (a, g)) -> StateT g m a) -> (g -> (a, g)) -> RandT g m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (g -> (a, g)) -> StateT g m a
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state ((g -> (a, g)) -> RandT g m a) -> (g -> (a, g)) -> RandT g m a
forall a b. (a -> b) -> a -> b
$ (a, a) -> g -> (a, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (a, a)
lohi
  getRandom :: RandT g m a
getRandom = StateT g m a -> RandT g m a
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m a -> RandT g m a)
-> ((g -> (a, g)) -> StateT g m a) -> (g -> (a, g)) -> RandT g m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (g -> (a, g)) -> StateT g m a
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state ((g -> (a, g)) -> RandT g m a) -> (g -> (a, g)) -> RandT g m a
forall a b. (a -> b) -> a -> b
$ g -> (a, g)
forall a g. (Random a, RandomGen g) => g -> (a, g)
random
  getRandomRs :: (a, a) -> RandT g m [a]
getRandomRs (a, a)
lohi = StateT g m [a] -> RandT g m [a]
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m [a] -> RandT g m [a])
-> ((g -> ([a], g)) -> StateT g m [a])
-> (g -> ([a], g))
-> RandT g m [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (g -> ([a], g)) -> StateT g m [a]
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state ((g -> ([a], g)) -> RandT g m [a])
-> (g -> ([a], g)) -> RandT g m [a]
forall a b. (a -> b) -> a -> b
$ (g -> [a]) -> (g, g) -> ([a], g)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first ((a, a) -> g -> [a]
forall a g. (Random a, RandomGen g) => (a, a) -> g -> [a]
randomRs (a, a)
lohi) ((g, g) -> ([a], g)) -> (g -> (g, g)) -> g -> ([a], g)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. g -> (g, g)
forall g. RandomGen g => g -> (g, g)
split
  getRandoms :: RandT g m [a]
getRandoms = StateT g m [a] -> RandT g m [a]
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m [a] -> RandT g m [a])
-> ((g -> ([a], g)) -> StateT g m [a])
-> (g -> ([a], g))
-> RandT g m [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (g -> ([a], g)) -> StateT g m [a]
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state ((g -> ([a], g)) -> RandT g m [a])
-> (g -> ([a], g)) -> RandT g m [a]
forall a b. (a -> b) -> a -> b
$ (g -> [a]) -> (g, g) -> ([a], g)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first g -> [a]
forall a g. (Random a, RandomGen g) => g -> [a]
randoms ((g, g) -> ([a], g)) -> (g -> (g, g)) -> g -> ([a], g)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. g -> (g, g)
forall g. RandomGen g => g -> (g, g)
split

instance (RandomGen g, Monad m) => MonadSplit g (RandT g m) where
  getSplit :: RandT g m g
getSplit = StateT g m g -> RandT g m g
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m g -> RandT g m g)
-> ((g -> (g, g)) -> StateT g m g) -> (g -> (g, g)) -> RandT g m g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (g -> (g, g)) -> StateT g m g
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state ((g -> (g, g)) -> RandT g m g) -> (g -> (g, g)) -> RandT g m g
forall a b. (a -> b) -> a -> b
$ g -> (g, g)
forall g. RandomGen g => g -> (g, g)
split

instance (Monad m, RandomGen g) => MonadInterleave (RandT g m) where
  interleave :: RandT g m a -> RandT g m a
interleave (RandT StateT g m a
m) = (g -> m (a, g)) -> RandT g m a
forall g (m :: * -> *) a. (g -> m (a, g)) -> RandT g m a
liftRandT ((g -> m (a, g)) -> RandT g m a) -> (g -> m (a, g)) -> RandT g m a
forall a b. (a -> b) -> a -> b
$ \g
g -> case g -> (g, g)
forall g. RandomGen g => g -> (g, g)
split g
g of
    (g
gl, g
gr) -> ((a, g) -> (a, g)) -> m (a, g) -> m (a, g)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (\(a, g)
p -> ((a, g) -> a
forall a b. (a, b) -> a
fst (a, g)
p, g
gr)) (m (a, g) -> m (a, g)) -> m (a, g) -> m (a, g)
forall a b. (a -> b) -> a -> b
$ StateT g m a -> g -> m (a, g)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
StrictState.runStateT StateT g m a
m g
gl

instance (MonadState s m) => MonadState s (RandT g m) where
  get :: RandT g m s
get = m s -> RandT g m s
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m s
forall s (m :: * -> *). MonadState s m => m s
get
  put :: s -> RandT g m ()
put = m () -> RandT g m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RandT g m ()) -> (s -> m ()) -> s -> RandT g m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> m ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put

instance PrimMonad m => PrimMonad (RandT s m) where
  type PrimState (RandT s m) = PrimState m
  primitive :: (State# (PrimState (RandT s m))
 -> (# State# (PrimState (RandT s m)), a #))
-> RandT s m a
primitive = m a -> RandT s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> RandT s m a)
-> ((State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a)
-> (State# (PrimState m) -> (# State# (PrimState m), a #))
-> RandT s m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive

instance Fail.MonadFail m => Fail.MonadFail (RandT g m) where
  fail :: String -> RandT g m a
fail = m a -> RandT g m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> RandT g m a) -> (String -> m a) -> String -> RandT g m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
Fail.fail

-- | Uniform lifting of a @callCC@ operation to the new monad.
-- This version rolls back to the original state on entering the
-- continuation.
liftCallCC :: CallCC m (a, g) (b, g) -> CallCC (RandT g m) a b
liftCallCC :: CallCC m (a, g) (b, g) -> CallCC (RandT g m) a b
liftCallCC CallCC m (a, g) (b, g)
callCC_ (a -> RandT g m b) -> RandT g m a
f = StateT g m a -> RandT g m a
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m a -> RandT g m a) -> StateT g m a -> RandT g m a
forall a b. (a -> b) -> a -> b
$ CallCC m (a, g) (b, g) -> CallCC (StateT g m) a b
forall (m :: * -> *) a s b.
CallCC m (a, s) (b, s) -> CallCC (StateT s m) a b
StrictState.liftCallCC CallCC m (a, g) (b, g)
callCC_ CallCC (StateT g m) a b -> CallCC (StateT g m) a b
forall a b. (a -> b) -> a -> b
$ \a -> StateT g m b
c -> RandT g m a -> StateT g m a
forall g (m :: * -> *) a. RandT g m a -> StateT g m a
unRandT ((a -> RandT g m b) -> RandT g m a
f (StateT g m b -> RandT g m b
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m b -> RandT g m b)
-> (a -> StateT g m b) -> a -> RandT g m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> StateT g m b
c))

-- | In-situ lifting of a @callCC@ operation to the new monad.
-- This version uses the current state on entering the continuation.
-- It does not satisfy the uniformity property (see "Control.Monad.Signatures").
liftCallCC' :: CallCC m (a, g) (b, g) -> CallCC (RandT g m) a b
liftCallCC' :: CallCC m (a, g) (b, g) -> CallCC (RandT g m) a b
liftCallCC' CallCC m (a, g) (b, g)
callCC_ (a -> RandT g m b) -> RandT g m a
f = StateT g m a -> RandT g m a
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m a -> RandT g m a) -> StateT g m a -> RandT g m a
forall a b. (a -> b) -> a -> b
$ CallCC m (a, g) (b, g) -> CallCC (StateT g m) a b
forall (m :: * -> *) a s b.
CallCC m (a, s) (b, s) -> CallCC (StateT s m) a b
StrictState.liftCallCC' CallCC m (a, g) (b, g)
callCC_ CallCC (StateT g m) a b -> CallCC (StateT g m) a b
forall a b. (a -> b) -> a -> b
$ \a -> StateT g m b
c -> RandT g m a -> StateT g m a
forall g (m :: * -> *) a. RandT g m a -> StateT g m a
unRandT ((a -> RandT g m b) -> RandT g m a
f (StateT g m b -> RandT g m b
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m b -> RandT g m b)
-> (a -> StateT g m b) -> a -> RandT g m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> StateT g m b
c))

-- | Lift a @catchE@ operation to the new monad.
liftCatch :: Catch e m (a, g) -> Catch e (RandT g m) a
liftCatch :: Catch e m (a, g) -> Catch e (RandT g m) a
liftCatch Catch e m (a, g)
catchE_ RandT g m a
m e -> RandT g m a
f = StateT g m a -> RandT g m a
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m a -> RandT g m a) -> StateT g m a -> RandT g m a
forall a b. (a -> b) -> a -> b
$ Catch e m (a, g) -> Catch e (StateT g m) a
forall e (m :: * -> *) a s.
Catch e m (a, s) -> Catch e (StateT s m) a
StrictState.liftCatch Catch e m (a, g)
catchE_ (RandT g m a -> StateT g m a
forall g (m :: * -> *) a. RandT g m a -> StateT g m a
unRandT RandT g m a
m) (RandT g m a -> StateT g m a
forall g (m :: * -> *) a. RandT g m a -> StateT g m a
unRandT (RandT g m a -> StateT g m a)
-> (e -> RandT g m a) -> e -> StateT g m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> RandT g m a
f)

-- | Lift a @listen@ operation to the new monad.
liftListen :: (Monad m) => Listen w m (a, g) -> Listen w (RandT g m) a
liftListen :: Listen w m (a, g) -> Listen w (RandT g m) a
liftListen Listen w m (a, g)
listen_ RandT g m a
m = StateT g m (a, w) -> RandT g m (a, w)
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m (a, w) -> RandT g m (a, w))
-> StateT g m (a, w) -> RandT g m (a, w)
forall a b. (a -> b) -> a -> b
$ Listen w m (a, g) -> Listen w (StateT g m) a
forall (m :: * -> *) w a s.
Monad m =>
Listen w m (a, s) -> Listen w (StateT s m) a
StrictState.liftListen Listen w m (a, g)
listen_ (RandT g m a -> StateT g m a
forall g (m :: * -> *) a. RandT g m a -> StateT g m a
unRandT RandT g m a
m)

-- | Lift a @pass@ operation to the new monad.
liftPass :: (Monad m) => Pass w m (a, g) -> Pass w (RandT g m) a
liftPass :: Pass w m (a, g) -> Pass w (RandT g m) a
liftPass Pass w m (a, g)
pass_ RandT g m (a, w -> w)
m = StateT g m a -> RandT g m a
forall g (m :: * -> *) a. StateT g m a -> RandT g m a
RandT (StateT g m a -> RandT g m a) -> StateT g m a -> RandT g m a
forall a b. (a -> b) -> a -> b
$ Pass w m (a, g) -> Pass w (StateT g m) a
forall (m :: * -> *) w a s.
Monad m =>
Pass w m (a, s) -> Pass w (StateT s m) a
StrictState.liftPass Pass w m (a, g)
pass_ (RandT g m (a, w -> w) -> StateT g m (a, w -> w)
forall g (m :: * -> *) a. RandT g m a -> StateT g m a
unRandT RandT g m (a, w -> w)
m)

-- | Evaluate a random computation in the `IO` monad, splitting the global
-- standard generator to get a new one for the computation.
evalRandIO :: Rand StdGen a -> IO a
evalRandIO :: Rand StdGen a -> IO a
evalRandIO Rand StdGen a
t = (StdGen -> a) -> IO StdGen -> IO a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (Rand StdGen a -> StdGen -> a
forall g a. Rand g a -> g -> a
evalRand Rand StdGen a
t) IO StdGen
forall (m :: * -> *). MonadIO m => m StdGen
newStdGen

-- | Evaluate a random computation that is embedded in the `IO` monad,
-- splitting the global standard generator to get a new one for the
-- computation.
evalRandTIO :: (MonadIO m) => RandT StdGen m a -> m a
evalRandTIO :: RandT StdGen m a -> m a
evalRandTIO RandT StdGen m a
t = IO StdGen -> m StdGen
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO StdGen
forall (m :: * -> *). MonadIO m => m StdGen
newStdGen m StdGen -> (StdGen -> m a) -> m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= RandT StdGen m a -> StdGen -> m a
forall (m :: * -> *) g a. Monad m => RandT g m a -> g -> m a
evalRandT RandT StdGen m a
t


-- | A proxy that carries information about the type of generator to use with @RandT@
-- monad and its `StatefulGen` instance.
--
-- @since 0.5.3
data RandGen g = RandGen

#if MIN_VERSION_random(1,2,0)
-- |
--
-- @since 0.5.3
instance (Monad m, RandomGen g) => StatefulGen (RandGen g) (RandT g m) where
  uniformWord32R :: Word32 -> RandGen g -> RandT g m Word32
uniformWord32R Word32
r = (g -> (Word32, g)) -> RandGen g -> RandT g m Word32
forall (m :: * -> *) g a.
Applicative m =>
(g -> (a, g)) -> RandGen g -> RandT g m a
applyRandT (Word32 -> g -> (Word32, g)
forall g. RandomGen g => Word32 -> g -> (Word32, g)
genWord32R Word32
r)
  uniformWord64R :: Word64 -> RandGen g -> RandT g m Word64
uniformWord64R Word64
r = (g -> (Word64, g)) -> RandGen g -> RandT g m Word64
forall (m :: * -> *) g a.
Applicative m =>
(g -> (a, g)) -> RandGen g -> RandT g m a
applyRandT (Word64 -> g -> (Word64, g)
forall g. RandomGen g => Word64 -> g -> (Word64, g)
genWord64R Word64
r)
  uniformWord8 :: RandGen g -> RandT g m Word8
uniformWord8 = (g -> (Word8, g)) -> RandGen g -> RandT g m Word8
forall (m :: * -> *) g a.
Applicative m =>
(g -> (a, g)) -> RandGen g -> RandT g m a
applyRandT g -> (Word8, g)
forall g. RandomGen g => g -> (Word8, g)
genWord8
  uniformWord16 :: RandGen g -> RandT g m Word16
uniformWord16 = (g -> (Word16, g)) -> RandGen g -> RandT g m Word16
forall (m :: * -> *) g a.
Applicative m =>
(g -> (a, g)) -> RandGen g -> RandT g m a
applyRandT g -> (Word16, g)
forall g. RandomGen g => g -> (Word16, g)
genWord16
  uniformWord32 :: RandGen g -> RandT g m Word32
uniformWord32 = (g -> (Word32, g)) -> RandGen g -> RandT g m Word32
forall (m :: * -> *) g a.
Applicative m =>
(g -> (a, g)) -> RandGen g -> RandT g m a
applyRandT g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
genWord32
  uniformWord64 :: RandGen g -> RandT g m Word64
uniformWord64 = (g -> (Word64, g)) -> RandGen g -> RandT g m Word64
forall (m :: * -> *) g a.
Applicative m =>
(g -> (a, g)) -> RandGen g -> RandT g m a
applyRandT g -> (Word64, g)
forall g. RandomGen g => g -> (Word64, g)
genWord64
  uniformShortByteString :: Int -> RandGen g -> RandT g m ShortByteString
uniformShortByteString Int
n = (g -> (ShortByteString, g))
-> RandGen g -> RandT g m ShortByteString
forall (m :: * -> *) g a.
Applicative m =>
(g -> (a, g)) -> RandGen g -> RandT g m a
applyRandT (Int -> g -> (ShortByteString, g)
forall g. RandomGen g => Int -> g -> (ShortByteString, g)
genShortByteString Int
n)

-- |
--
-- @since 0.5.3
instance (Monad m, RandomGen g) => RandomGenM (RandGen g) g (RandT g m) where
  applyRandomGenM :: (g -> (a, g)) -> RandGen g -> RandT g m a
applyRandomGenM = (g -> (a, g)) -> RandGen g -> RandT g m a
forall (m :: * -> *) g a.
Applicative m =>
(g -> (a, g)) -> RandGen g -> RandT g m a
applyRandT

applyRandT :: Applicative m => (g -> (a, g)) -> RandGen g -> RandT g m a
applyRandT :: (g -> (a, g)) -> RandGen g -> RandT g m a
applyRandT g -> (a, g)
f RandGen g
_ = (g -> m (a, g)) -> RandT g m a
forall g (m :: * -> *) a. (g -> m (a, g)) -> RandT g m a
liftRandT ((a, g) -> m (a, g)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((a, g) -> m (a, g)) -> (g -> (a, g)) -> g -> m (a, g)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. g -> (a, g)
f)
#endif

-- | A `RandT` runner that allows using it with `StatefulGen` restricted actions. Returns
-- the outcome of random computation and the new pseudo-random-number generator
--
-- >>> withRandGen (mkStdGen 2021) uniformM :: IO (Int, StdGen)
-- (6070831465987696718,StdGen {unStdGen = SMGen 4687568268719557181 4805600293067301895})
--
-- @since 0.5.3
withRandGen ::
     g
  -- ^ initial generator
  -> (RandGen g -> RandT g m a)
  -> m (a, g)
  -- ^ return value and final generator
withRandGen :: g -> (RandGen g -> RandT g m a) -> m (a, g)
withRandGen g
g RandGen g -> RandT g m a
action = RandT g m a -> g -> m (a, g)
forall g (m :: * -> *) a. RandT g m a -> g -> m (a, g)
runRandT (RandGen g -> RandT g m a
action RandGen g
forall g. RandGen g
RandGen) g
g

-- | Same as `withRandGen`, but discards the resulting generator.
--
-- >>> withRandGen_ (mkStdGen 2021) uniformM :: IO Int
-- 6070831465987696718
--
-- @since 0.5.3
withRandGen_ ::
     Monad m
  => g
  -- ^ initial generator
  -> (RandGen g -> RandT g m a)
  -> m a
  -- ^ return value and final generator
withRandGen_ :: g -> (RandGen g -> RandT g m a) -> m a
withRandGen_ g
g RandGen g -> RandT g m a
action = RandT g m a -> g -> m a
forall (m :: * -> *) g a. Monad m => RandT g m a -> g -> m a
evalRandT (RandGen g -> RandT g m a
action RandGen g
forall g. RandGen g
RandGen) g
g


{- $examples

The @die@ function simulates the roll of a die, picking a number between 1
and 6, inclusive, and returning it in the 'Rand' monad transformer.  Notice
that this code will work with any random number generator @g@.

> die :: (RandomGen g) => Rand g Int
> die = getRandomR (1, 6)

The @dice@ function uses @replicate@ and @sequence@ to simulate the roll of
@n@ dice.

> dice :: (RandomGen g) => Int -> Rand g [Int]
> dice n = sequence (replicate n die)

To extract a value from the 'Rand' monad transformer, we can use 'evalRandIO'.

> main = do
>   values <- evalRandIO (dice 2)
>   putStrLn (show values)

-}