{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

-- |
-- Module      :  System.Random.Stateful
-- Copyright   :  (c) The University of Glasgow 2001
-- License     :  BSD-style (see the file LICENSE in the 'random' repository)
-- Maintainer  :  libraries@haskell.org
-- Stability   :  stable
--
-- This library deals with the common task of pseudo-random number generation.
module System.Random.Stateful
  (
  -- * Pure Random Generator
  module System.Random
  -- * Monadic Random Generator
  -- $introduction

  -- * Usage
  -- $usagemonadic

  -- * Mutable pseudo-random number generator interfaces
  -- $interfaces
  , StatefulGen(..)
  , FrozenGen(..)
  , RandomGenM(..)
  , withMutableGen
  , withMutableGen_
  , randomM
  , randomRM
  , splitGenM

  -- * Monadic adapters for pure pseudo-random number generators #monadicadapters#
  -- $monadicadapters

  -- ** Pure adapter
  , StateGen(..)
  , StateGenM(..)
  , runStateGen
  , runStateGen_
  , runStateGenT
  , runStateGenT_
  , runStateGenST
  -- ** Mutable adapter with atomic operations
  , AtomicGen(..)
  , AtomicGenM(..)
  , newAtomicGenM
  , applyAtomicGen
  -- ** Mutable adapter in 'IO'
  , IOGen(..)
  , IOGenM(..)
  , newIOGenM
  , applyIOGen
  -- ** Mutable adapter in 'ST'
  , STGen(..)
  , STGenM(..)
  , newSTGenM
  , applySTGen
  , runSTGen
  , runSTGen_

  -- * Pseudo-random values of various types
  -- $uniform
  , Uniform(..)
  , uniformListM
  , UniformRange(..)

  -- * Generators for sequences of pseudo-random bytes
  , genShortByteStringIO
  , genShortByteStringST
  , uniformByteStringM
  , uniformDouble01M
  , uniformDoublePositive01M
  , uniformFloat01M
  , uniformFloatPositive01M

  -- * Appendix

  -- ** How to implement 'StatefulGen'
  -- $implementmonadrandom

  -- ** Floating point number caveats #fpcaveats#
  -- $floating

  -- * References
  -- $references
  ) where

import Control.DeepSeq
import Control.Monad.IO.Class
import Control.Monad.ST
import Control.Monad.State.Strict
import Data.IORef
import Data.STRef
import Foreign.Storable
import System.Random
import System.Random.Internal

-- $introduction
--
-- This module provides type classes and instances for the following concepts:
--
-- [Monadic pseudo-random number generators] 'StatefulGen' is an interface to
--     monadic pseudo-random number generators.
--
-- [Monadic adapters] 'StateGenM', 'AtomicGenM', 'IOGenM' and 'STGenM' turn a
--     'RandomGen' instance into a 'StatefulGen' instance.
--
-- [Drawing from a range] 'UniformRange' is used to generate a value of a
--     type uniformly within a range.
--
--     This library provides instances of 'UniformRange' for many common
--     numeric types.
--
-- [Drawing from the entire domain of a type] 'Uniform' is used to generate a
--     value of a type uniformly over all possible values of that type.
--
--     This library provides instances of 'Uniform' for many common bounded
--     numeric types.
--
-- $usagemonadic
--
-- In monadic code, use the relevant 'Uniform' and 'UniformRange' instances to
-- generate pseudo-random values via 'uniformM' and 'uniformRM', respectively.
--
-- As an example, @rollsM@ generates @n@ pseudo-random values of @Word@ in the
-- range @[1, 6]@ in a 'StatefulGen' context; given a /monadic/ pseudo-random
-- number generator, you can run this probabilistic computation as follows:
--
-- >>> :{
-- let rollsM :: StatefulGen g m => Int -> g -> m [Word]
--     rollsM n = replicateM n . uniformRM (1, 6)
-- in do
--     monadicGen <- MWC.create
--     rollsM 10 monadicGen :: IO [Word]
-- :}
-- [3,4,3,1,4,6,1,6,1,4]
--
-- Given a /pure/ pseudo-random number generator, you can run the monadic
-- pseudo-random number computation @rollsM@ in an 'IO' or 'ST' context by
-- applying a monadic adapter like 'AtomicGenM', 'IOGenM' or 'STGenM'
-- (see [monadic-adapters](#monadicadapters)) to the pure pseudo-random number
-- generator.
--
-- >>> :{
-- let rollsM :: StatefulGen g m => Int -> g -> m [Word]
--     rollsM n = replicateM n . uniformRM (1, 6)
--     pureGen = mkStdGen 42
-- in
--     newIOGenM pureGen >>= rollsM 10 :: IO [Word]
-- :}
-- [1,1,3,2,4,5,3,4,6,2]

-------------------------------------------------------------------------------
-- Pseudo-random number generator interfaces
-------------------------------------------------------------------------------

-- $interfaces
--
-- Pseudo-random number generators come in two flavours: /pure/ and /monadic/.
--
-- ['System.Random.RandomGen': pure pseudo-random number generators]
--     See "System.Random" module.
--
-- ['StatefulGen': monadic pseudo-random number generators] These generators
--     mutate their own state as they produce pseudo-random values. They
--     generally live in 'ST' or 'IO' or some transformer that implements
--     @PrimMonad@.
--

-------------------------------------------------------------------------------
-- Monadic adapters
-------------------------------------------------------------------------------

-- $monadicadapters
--
-- Pure pseudo-random number generators can be used in monadic code via the
-- adapters 'StateGenM', 'AtomicGenM', 'IOGenM' and 'STGenM'.
--
-- *   'StateGenM' can be used in any state monad. With strict 'StateT' there is
--     no performance overhead compared to using the 'RandomGen' instance
--     directly. 'StateGenM' is /not/ safe to use in the presence of exceptions
--     and concurrency.
--
-- *   'AtomicGenM' is safe in the presence of exceptions and concurrency since
--     it performs all actions atomically.
--
-- *   'IOGenM' is a wrapper around an 'IORef' that holds a pure generator.
--     'IOGenM' is safe in the presence of exceptions, but not concurrency.
--
-- *   'STGenM' is a wrapper around an 'STRef' that holds a pure generator.
--     'STGenM' is safe in the presence of exceptions, but not concurrency.

-- | Interface to operations on 'RandomGen' wrappers like 'IOGenM' and 'StateGenM'.
--
-- @since 1.2.0
class (RandomGen r, StatefulGen g m) => RandomGenM g r m | g -> r where
  applyRandomGenM :: (r -> (a, r)) -> g -> m a

-- | Splits a pseudo-random number generator into two. Overwrites the mutable
-- wrapper with one of the resulting generators and returns the other.
--
-- @since 1.2.0
splitGenM :: RandomGenM g r m => g -> m r
splitGenM :: g -> m r
splitGenM = (r -> (r, r)) -> g -> m r
forall g r (m :: * -> *) a.
RandomGenM g r m =>
(r -> (a, r)) -> g -> m a
applyRandomGenM r -> (r, r)
forall g. RandomGen g => g -> (g, g)
split

instance (RandomGen r, MonadIO m) => RandomGenM (IOGenM r) r m where
  applyRandomGenM :: (r -> (a, r)) -> IOGenM r -> m a
applyRandomGenM = (r -> (a, r)) -> IOGenM r -> m a
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> IOGenM g -> m a
applyIOGen

instance (RandomGen r, MonadIO m) => RandomGenM (AtomicGenM r) r m where
  applyRandomGenM :: (r -> (a, r)) -> AtomicGenM r -> m a
applyRandomGenM = (r -> (a, r)) -> AtomicGenM r -> m a
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> AtomicGenM g -> m a
applyAtomicGen

instance (RandomGen r, MonadState r m) => RandomGenM (StateGenM r) r m where
  applyRandomGenM :: (r -> (a, r)) -> StateGenM r -> m a
applyRandomGenM r -> (a, r)
f StateGenM r
_ = (r -> (a, r)) -> m a
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state r -> (a, r)
f

instance RandomGen r => RandomGenM (STGenM r s) r (ST s) where
  applyRandomGenM :: (r -> (a, r)) -> STGenM r s -> ST s a
applyRandomGenM = (r -> (a, r)) -> STGenM r s -> ST s a
forall g a s. (g -> (a, g)) -> STGenM g s -> ST s a
applySTGen


-- | Runs a mutable pseudo-random number generator from its 'Frozen' state.
--
-- ====__Examples__
--
-- >>> import Data.Int (Int8)
-- >>> withMutableGen (IOGen (mkStdGen 217)) (uniformListM 5) :: IO ([Int8], IOGen StdGen)
-- ([-74,37,-50,-2,3],IOGen {unIOGen = StdGen {unStdGen = SMGen 4273268533320920145 15251669095119325999}})
--
-- @since 1.2.0
withMutableGen :: FrozenGen f m => f -> (MutableGen f m -> m a) -> m (a, f)
withMutableGen :: f -> (MutableGen f m -> m a) -> m (a, f)
withMutableGen f
fg MutableGen f m -> m a
action = do
  MutableGen f m
g <- f -> m (MutableGen f m)
forall f (m :: * -> *). FrozenGen f m => f -> m (MutableGen f m)
thawGen f
fg
  a
res <- MutableGen f m -> m a
action MutableGen f m
g
  f
fg' <- MutableGen f m -> m f
forall f (m :: * -> *). FrozenGen f m => MutableGen f m -> m f
freezeGen MutableGen f m
g
  (a, f) -> m (a, f)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
res, f
fg')

-- | Same as 'withMutableGen', but only returns the generated value.
--
-- ====__Examples__
--
-- >>> import System.Random.Stateful
-- >>> let pureGen = mkStdGen 137
-- >>> withMutableGen_ (IOGen pureGen) (uniformRM (1 :: Int, 6 :: Int))
-- 4
--
-- @since 1.2.0
withMutableGen_ :: FrozenGen f m => f -> (MutableGen f m -> m a) -> m a
withMutableGen_ :: f -> (MutableGen f m -> m a) -> m a
withMutableGen_ f
fg MutableGen f m -> m a
action = (a, f) -> a
forall a b. (a, b) -> a
fst ((a, f) -> a) -> m (a, f) -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f -> (MutableGen f m -> m a) -> m (a, f)
forall f (m :: * -> *) a.
FrozenGen f m =>
f -> (MutableGen f m -> m a) -> m (a, f)
withMutableGen f
fg MutableGen f m -> m a
action


-- | Generates a list of pseudo-random values.
--
-- ====__Examples__
--
-- >>> import System.Random.Stateful
-- >>> let pureGen = mkStdGen 137
-- >>> g <- newIOGenM pureGen
-- >>> uniformListM 10 g :: IO [Bool]
-- [True,True,True,True,False,True,True,False,False,False]
--
-- @since 1.2.0
uniformListM :: (StatefulGen g m, Uniform a) => Int -> g -> m [a]
uniformListM :: Int -> g -> m [a]
uniformListM Int
n g
gen = Int -> m a -> m [a]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
n (g -> m a
forall a g (m :: * -> *). (Uniform a, StatefulGen g m) => g -> m a
uniformM g
gen)

-- | Generates a pseudo-random value using monadic interface and `Random` instance.
--
-- ====__Examples__
--
-- >>> import System.Random.Stateful
-- >>> let pureGen = mkStdGen 137
-- >>> g <- newIOGenM pureGen
-- >>> randomM g :: IO Double
-- 0.5728354935654512
--
-- @since 1.2.0
randomM :: (RandomGenM g r m, Random a) => g -> m a
randomM :: g -> m a
randomM = (r -> (a, r)) -> g -> m a
forall g r (m :: * -> *) a.
RandomGenM g r m =>
(r -> (a, r)) -> g -> m a
applyRandomGenM r -> (a, r)
forall a g. (Random a, RandomGen g) => g -> (a, g)
random

-- | Generates a pseudo-random value using monadic interface and `Random` instance.
--
-- ====__Examples__
--
-- >>> import System.Random.Stateful
-- >>> let pureGen = mkStdGen 137
-- >>> g <- newIOGenM pureGen
-- >>> randomRM (1, 100) g :: IO Int
-- 52
--
-- @since 1.2.0
randomRM :: (RandomGenM g r m, Random a) => (a, a) -> g -> m a
randomRM :: (a, a) -> g -> m a
randomRM (a, a)
r = (r -> (a, r)) -> g -> m a
forall g r (m :: * -> *) a.
RandomGenM g r m =>
(r -> (a, r)) -> g -> m a
applyRandomGenM ((a, a) -> r -> (a, r)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (a, a)
r)

-- | Wraps an 'IORef' that holds a pure pseudo-random number generator. All
-- operations are performed atomically.
--
-- *   'AtomicGenM' is safe in the presence of exceptions and concurrency.
-- *   'AtomicGenM' is the slowest of the monadic adapters due to the overhead
--     of its atomic operations.
--
-- @since 1.2.0
newtype AtomicGenM g = AtomicGenM { AtomicGenM g -> IORef g
unAtomicGenM :: IORef g}


-- | Frozen version of mutable `AtomicGenM` generator
--
-- @since 1.2.0
newtype AtomicGen g = AtomicGen { AtomicGen g -> g
unAtomicGen :: g}
  deriving (AtomicGen g -> AtomicGen g -> Bool
(AtomicGen g -> AtomicGen g -> Bool)
-> (AtomicGen g -> AtomicGen g -> Bool) -> Eq (AtomicGen g)
forall g. Eq g => AtomicGen g -> AtomicGen g -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AtomicGen g -> AtomicGen g -> Bool
$c/= :: forall g. Eq g => AtomicGen g -> AtomicGen g -> Bool
== :: AtomicGen g -> AtomicGen g -> Bool
$c== :: forall g. Eq g => AtomicGen g -> AtomicGen g -> Bool
Eq, Eq (AtomicGen g)
Eq (AtomicGen g)
-> (AtomicGen g -> AtomicGen g -> Ordering)
-> (AtomicGen g -> AtomicGen g -> Bool)
-> (AtomicGen g -> AtomicGen g -> Bool)
-> (AtomicGen g -> AtomicGen g -> Bool)
-> (AtomicGen g -> AtomicGen g -> Bool)
-> (AtomicGen g -> AtomicGen g -> AtomicGen g)
-> (AtomicGen g -> AtomicGen g -> AtomicGen g)
-> Ord (AtomicGen g)
AtomicGen g -> AtomicGen g -> Bool
AtomicGen g -> AtomicGen g -> Ordering
AtomicGen g -> AtomicGen g -> AtomicGen g
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall g. Ord g => Eq (AtomicGen g)
forall g. Ord g => AtomicGen g -> AtomicGen g -> Bool
forall g. Ord g => AtomicGen g -> AtomicGen g -> Ordering
forall g. Ord g => AtomicGen g -> AtomicGen g -> AtomicGen g
min :: AtomicGen g -> AtomicGen g -> AtomicGen g
$cmin :: forall g. Ord g => AtomicGen g -> AtomicGen g -> AtomicGen g
max :: AtomicGen g -> AtomicGen g -> AtomicGen g
$cmax :: forall g. Ord g => AtomicGen g -> AtomicGen g -> AtomicGen g
>= :: AtomicGen g -> AtomicGen g -> Bool
$c>= :: forall g. Ord g => AtomicGen g -> AtomicGen g -> Bool
> :: AtomicGen g -> AtomicGen g -> Bool
$c> :: forall g. Ord g => AtomicGen g -> AtomicGen g -> Bool
<= :: AtomicGen g -> AtomicGen g -> Bool
$c<= :: forall g. Ord g => AtomicGen g -> AtomicGen g -> Bool
< :: AtomicGen g -> AtomicGen g -> Bool
$c< :: forall g. Ord g => AtomicGen g -> AtomicGen g -> Bool
compare :: AtomicGen g -> AtomicGen g -> Ordering
$ccompare :: forall g. Ord g => AtomicGen g -> AtomicGen g -> Ordering
$cp1Ord :: forall g. Ord g => Eq (AtomicGen g)
Ord, Int -> AtomicGen g -> ShowS
[AtomicGen g] -> ShowS
AtomicGen g -> String
(Int -> AtomicGen g -> ShowS)
-> (AtomicGen g -> String)
-> ([AtomicGen g] -> ShowS)
-> Show (AtomicGen g)
forall g. Show g => Int -> AtomicGen g -> ShowS
forall g. Show g => [AtomicGen g] -> ShowS
forall g. Show g => AtomicGen g -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AtomicGen g] -> ShowS
$cshowList :: forall g. Show g => [AtomicGen g] -> ShowS
show :: AtomicGen g -> String
$cshow :: forall g. Show g => AtomicGen g -> String
showsPrec :: Int -> AtomicGen g -> ShowS
$cshowsPrec :: forall g. Show g => Int -> AtomicGen g -> ShowS
Show, Int -> AtomicGen g -> (ShortByteString, AtomicGen g)
Word32 -> AtomicGen g -> (Word32, AtomicGen g)
Word64 -> AtomicGen g -> (Word64, AtomicGen g)
AtomicGen g -> (Int, Int)
AtomicGen g -> (Int, AtomicGen g)
AtomicGen g -> (Word8, AtomicGen g)
AtomicGen g -> (Word16, AtomicGen g)
AtomicGen g -> (Word32, AtomicGen g)
AtomicGen g -> (Word64, AtomicGen g)
AtomicGen g -> (AtomicGen g, AtomicGen g)
(AtomicGen g -> (Int, AtomicGen g))
-> (AtomicGen g -> (Word8, AtomicGen g))
-> (AtomicGen g -> (Word16, AtomicGen g))
-> (AtomicGen g -> (Word32, AtomicGen g))
-> (AtomicGen g -> (Word64, AtomicGen g))
-> (Word32 -> AtomicGen g -> (Word32, AtomicGen g))
-> (Word64 -> AtomicGen g -> (Word64, AtomicGen g))
-> (Int -> AtomicGen g -> (ShortByteString, AtomicGen g))
-> (AtomicGen g -> (Int, Int))
-> (AtomicGen g -> (AtomicGen g, AtomicGen g))
-> RandomGen (AtomicGen g)
forall g.
RandomGen g =>
Int -> AtomicGen g -> (ShortByteString, AtomicGen g)
forall g.
RandomGen g =>
Word32 -> AtomicGen g -> (Word32, AtomicGen g)
forall g.
RandomGen g =>
Word64 -> AtomicGen g -> (Word64, AtomicGen g)
forall g. RandomGen g => AtomicGen g -> (Int, Int)
forall g. RandomGen g => AtomicGen g -> (Int, AtomicGen g)
forall g. RandomGen g => AtomicGen g -> (Word8, AtomicGen g)
forall g. RandomGen g => AtomicGen g -> (Word16, AtomicGen g)
forall g. RandomGen g => AtomicGen g -> (Word32, AtomicGen g)
forall g. RandomGen g => AtomicGen g -> (Word64, AtomicGen g)
forall g. RandomGen g => AtomicGen g -> (AtomicGen g, AtomicGen g)
forall g.
(g -> (Int, g))
-> (g -> (Word8, g))
-> (g -> (Word16, g))
-> (g -> (Word32, g))
-> (g -> (Word64, g))
-> (Word32 -> g -> (Word32, g))
-> (Word64 -> g -> (Word64, g))
-> (Int -> g -> (ShortByteString, g))
-> (g -> (Int, Int))
-> (g -> (g, g))
-> RandomGen g
split :: AtomicGen g -> (AtomicGen g, AtomicGen g)
$csplit :: forall g. RandomGen g => AtomicGen g -> (AtomicGen g, AtomicGen g)
genRange :: AtomicGen g -> (Int, Int)
$cgenRange :: forall g. RandomGen g => AtomicGen g -> (Int, Int)
genShortByteString :: Int -> AtomicGen g -> (ShortByteString, AtomicGen g)
$cgenShortByteString :: forall g.
RandomGen g =>
Int -> AtomicGen g -> (ShortByteString, AtomicGen g)
genWord64R :: Word64 -> AtomicGen g -> (Word64, AtomicGen g)
$cgenWord64R :: forall g.
RandomGen g =>
Word64 -> AtomicGen g -> (Word64, AtomicGen g)
genWord32R :: Word32 -> AtomicGen g -> (Word32, AtomicGen g)
$cgenWord32R :: forall g.
RandomGen g =>
Word32 -> AtomicGen g -> (Word32, AtomicGen g)
genWord64 :: AtomicGen g -> (Word64, AtomicGen g)
$cgenWord64 :: forall g. RandomGen g => AtomicGen g -> (Word64, AtomicGen g)
genWord32 :: AtomicGen g -> (Word32, AtomicGen g)
$cgenWord32 :: forall g. RandomGen g => AtomicGen g -> (Word32, AtomicGen g)
genWord16 :: AtomicGen g -> (Word16, AtomicGen g)
$cgenWord16 :: forall g. RandomGen g => AtomicGen g -> (Word16, AtomicGen g)
genWord8 :: AtomicGen g -> (Word8, AtomicGen g)
$cgenWord8 :: forall g. RandomGen g => AtomicGen g -> (Word8, AtomicGen g)
next :: AtomicGen g -> (Int, AtomicGen g)
$cnext :: forall g. RandomGen g => AtomicGen g -> (Int, AtomicGen g)
RandomGen, Ptr b -> Int -> IO (AtomicGen g)
Ptr b -> Int -> AtomicGen g -> IO ()
Ptr (AtomicGen g) -> IO (AtomicGen g)
Ptr (AtomicGen g) -> Int -> IO (AtomicGen g)
Ptr (AtomicGen g) -> Int -> AtomicGen g -> IO ()
Ptr (AtomicGen g) -> AtomicGen g -> IO ()
AtomicGen g -> Int
(AtomicGen g -> Int)
-> (AtomicGen g -> Int)
-> (Ptr (AtomicGen g) -> Int -> IO (AtomicGen g))
-> (Ptr (AtomicGen g) -> Int -> AtomicGen g -> IO ())
-> (forall b. Ptr b -> Int -> IO (AtomicGen g))
-> (forall b. Ptr b -> Int -> AtomicGen g -> IO ())
-> (Ptr (AtomicGen g) -> IO (AtomicGen g))
-> (Ptr (AtomicGen g) -> AtomicGen g -> IO ())
-> Storable (AtomicGen g)
forall b. Ptr b -> Int -> IO (AtomicGen g)
forall b. Ptr b -> Int -> AtomicGen g -> IO ()
forall g. Storable g => Ptr (AtomicGen g) -> IO (AtomicGen g)
forall g.
Storable g =>
Ptr (AtomicGen g) -> Int -> IO (AtomicGen g)
forall g.
Storable g =>
Ptr (AtomicGen g) -> Int -> AtomicGen g -> IO ()
forall g. Storable g => Ptr (AtomicGen g) -> AtomicGen g -> IO ()
forall g. Storable g => AtomicGen g -> Int
forall g b. Storable g => Ptr b -> Int -> IO (AtomicGen g)
forall g b. Storable g => Ptr b -> Int -> AtomicGen g -> IO ()
forall a.
(a -> Int)
-> (a -> Int)
-> (Ptr a -> Int -> IO a)
-> (Ptr a -> Int -> a -> IO ())
-> (forall b. Ptr b -> Int -> IO a)
-> (forall b. Ptr b -> Int -> a -> IO ())
-> (Ptr a -> IO a)
-> (Ptr a -> a -> IO ())
-> Storable a
poke :: Ptr (AtomicGen g) -> AtomicGen g -> IO ()
$cpoke :: forall g. Storable g => Ptr (AtomicGen g) -> AtomicGen g -> IO ()
peek :: Ptr (AtomicGen g) -> IO (AtomicGen g)
$cpeek :: forall g. Storable g => Ptr (AtomicGen g) -> IO (AtomicGen g)
pokeByteOff :: Ptr b -> Int -> AtomicGen g -> IO ()
$cpokeByteOff :: forall g b. Storable g => Ptr b -> Int -> AtomicGen g -> IO ()
peekByteOff :: Ptr b -> Int -> IO (AtomicGen g)
$cpeekByteOff :: forall g b. Storable g => Ptr b -> Int -> IO (AtomicGen g)
pokeElemOff :: Ptr (AtomicGen g) -> Int -> AtomicGen g -> IO ()
$cpokeElemOff :: forall g.
Storable g =>
Ptr (AtomicGen g) -> Int -> AtomicGen g -> IO ()
peekElemOff :: Ptr (AtomicGen g) -> Int -> IO (AtomicGen g)
$cpeekElemOff :: forall g.
Storable g =>
Ptr (AtomicGen g) -> Int -> IO (AtomicGen g)
alignment :: AtomicGen g -> Int
$calignment :: forall g. Storable g => AtomicGen g -> Int
sizeOf :: AtomicGen g -> Int
$csizeOf :: forall g. Storable g => AtomicGen g -> Int
Storable, AtomicGen g -> ()
(AtomicGen g -> ()) -> NFData (AtomicGen g)
forall g. NFData g => AtomicGen g -> ()
forall a. (a -> ()) -> NFData a
rnf :: AtomicGen g -> ()
$crnf :: forall g. NFData g => AtomicGen g -> ()
NFData)

-- | Creates a new 'AtomicGenM'.
--
-- @since 1.2.0
newAtomicGenM :: MonadIO m => g -> m (AtomicGenM g)
newAtomicGenM :: g -> m (AtomicGenM g)
newAtomicGenM = (IORef g -> AtomicGenM g) -> m (IORef g) -> m (AtomicGenM g)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap IORef g -> AtomicGenM g
forall g. IORef g -> AtomicGenM g
AtomicGenM (m (IORef g) -> m (AtomicGenM g))
-> (g -> m (IORef g)) -> g -> m (AtomicGenM g)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (IORef g) -> m (IORef g)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (IORef g) -> m (IORef g))
-> (g -> IO (IORef g)) -> g -> m (IORef g)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. g -> IO (IORef g)
forall a. a -> IO (IORef a)
newIORef

instance (RandomGen g, MonadIO m) => StatefulGen (AtomicGenM g) m where
  uniformWord32R :: Word32 -> AtomicGenM g -> m Word32
uniformWord32R Word32
r = (g -> (Word32, g)) -> AtomicGenM g -> m Word32
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> AtomicGenM g -> m a
applyAtomicGen (Word32 -> g -> (Word32, g)
forall g. RandomGen g => Word32 -> g -> (Word32, g)
genWord32R Word32
r)
  {-# INLINE uniformWord32R #-}
  uniformWord64R :: Word64 -> AtomicGenM g -> m Word64
uniformWord64R Word64
r = (g -> (Word64, g)) -> AtomicGenM g -> m Word64
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> AtomicGenM g -> m a
applyAtomicGen (Word64 -> g -> (Word64, g)
forall g. RandomGen g => Word64 -> g -> (Word64, g)
genWord64R Word64
r)
  {-# INLINE uniformWord64R #-}
  uniformWord8 :: AtomicGenM g -> m Word8
uniformWord8 = (g -> (Word8, g)) -> AtomicGenM g -> m Word8
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> AtomicGenM g -> m a
applyAtomicGen g -> (Word8, g)
forall g. RandomGen g => g -> (Word8, g)
genWord8
  {-# INLINE uniformWord8 #-}
  uniformWord16 :: AtomicGenM g -> m Word16
uniformWord16 = (g -> (Word16, g)) -> AtomicGenM g -> m Word16
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> AtomicGenM g -> m a
applyAtomicGen g -> (Word16, g)
forall g. RandomGen g => g -> (Word16, g)
genWord16
  {-# INLINE uniformWord16 #-}
  uniformWord32 :: AtomicGenM g -> m Word32
uniformWord32 = (g -> (Word32, g)) -> AtomicGenM g -> m Word32
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> AtomicGenM g -> m a
applyAtomicGen g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
genWord32
  {-# INLINE uniformWord32 #-}
  uniformWord64 :: AtomicGenM g -> m Word64
uniformWord64 = (g -> (Word64, g)) -> AtomicGenM g -> m Word64
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> AtomicGenM g -> m a
applyAtomicGen g -> (Word64, g)
forall g. RandomGen g => g -> (Word64, g)
genWord64
  {-# INLINE uniformWord64 #-}
  uniformShortByteString :: Int -> AtomicGenM g -> m ShortByteString
uniformShortByteString Int
n = (g -> (ShortByteString, g)) -> AtomicGenM g -> m ShortByteString
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> AtomicGenM g -> m a
applyAtomicGen (Int -> g -> (ShortByteString, g)
forall g. RandomGen g => Int -> g -> (ShortByteString, g)
genShortByteString Int
n)


instance (RandomGen g, MonadIO m) => FrozenGen (AtomicGen g) m where
  type MutableGen (AtomicGen g) m = AtomicGenM g
  freezeGen :: MutableGen (AtomicGen g) m -> m (AtomicGen g)
freezeGen = (g -> AtomicGen g) -> m g -> m (AtomicGen g)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap g -> AtomicGen g
forall g. g -> AtomicGen g
AtomicGen (m g -> m (AtomicGen g))
-> (AtomicGenM g -> m g) -> AtomicGenM g -> m (AtomicGen g)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO g -> m g
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO g -> m g) -> (AtomicGenM g -> IO g) -> AtomicGenM g -> m g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IORef g -> IO g
forall a. IORef a -> IO a
readIORef (IORef g -> IO g)
-> (AtomicGenM g -> IORef g) -> AtomicGenM g -> IO g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AtomicGenM g -> IORef g
forall g. AtomicGenM g -> IORef g
unAtomicGenM
  thawGen :: AtomicGen g -> m (MutableGen (AtomicGen g) m)
thawGen (AtomicGen g
g) = g -> m (AtomicGenM g)
forall (m :: * -> *) g. MonadIO m => g -> m (AtomicGenM g)
newAtomicGenM g
g

-- | Atomically applies a pure operation to the wrapped pseudo-random number
-- generator.
--
-- ====__Examples__
--
-- >>> import System.Random.Stateful
-- >>> let pureGen = mkStdGen 137
-- >>> g <- newAtomicGenM pureGen
-- >>> applyAtomicGen random g :: IO Int
-- 7879794327570578227
--
-- @since 1.2.0
applyAtomicGen :: MonadIO m => (g -> (a, g)) -> (AtomicGenM g) -> m a
applyAtomicGen :: (g -> (a, g)) -> AtomicGenM g -> m a
applyAtomicGen g -> (a, g)
op (AtomicGenM IORef g
gVar) =
  IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ IORef g -> (g -> (g, a)) -> IO a
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef g
gVar ((g -> (g, a)) -> IO a) -> (g -> (g, a)) -> IO a
forall a b. (a -> b) -> a -> b
$ \g
g ->
    case g -> (a, g)
op g
g of
      (a
a, g
g') -> (g
g', a
a)
{-# INLINE applyAtomicGen #-}

-- | Wraps an 'IORef' that holds a pure pseudo-random number generator.
--
-- *   'IOGenM' is safe in the presence of exceptions, but not concurrency.
-- *   'IOGenM' is slower than 'StateGenM' due to the extra pointer indirection.
-- *   'IOGenM' is faster than 'AtomicGenM' since the 'IORef' operations used by
--     'IOGenM' are not atomic.
--
-- An example use case is writing pseudo-random bytes into a file:
--
-- >>> import UnliftIO.Temporary (withSystemTempFile)
-- >>> import Data.ByteString (hPutStr)
-- >>> let ioGen g = withSystemTempFile "foo.bin" $ \_ h -> uniformRM (0, 100) g >>= flip uniformByteStringM g >>= hPutStr h
--
-- and then run it:
--
-- >>> newIOGenM (mkStdGen 1729) >>= ioGen
--
-- @since 1.2.0
newtype IOGenM g = IOGenM { IOGenM g -> IORef g
unIOGenM :: IORef g }

-- | Frozen version of mutable `IOGenM` generator
--
-- @since 1.2.0
newtype IOGen g = IOGen { IOGen g -> g
unIOGen :: g }
  deriving (IOGen g -> IOGen g -> Bool
(IOGen g -> IOGen g -> Bool)
-> (IOGen g -> IOGen g -> Bool) -> Eq (IOGen g)
forall g. Eq g => IOGen g -> IOGen g -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IOGen g -> IOGen g -> Bool
$c/= :: forall g. Eq g => IOGen g -> IOGen g -> Bool
== :: IOGen g -> IOGen g -> Bool
$c== :: forall g. Eq g => IOGen g -> IOGen g -> Bool
Eq, Eq (IOGen g)
Eq (IOGen g)
-> (IOGen g -> IOGen g -> Ordering)
-> (IOGen g -> IOGen g -> Bool)
-> (IOGen g -> IOGen g -> Bool)
-> (IOGen g -> IOGen g -> Bool)
-> (IOGen g -> IOGen g -> Bool)
-> (IOGen g -> IOGen g -> IOGen g)
-> (IOGen g -> IOGen g -> IOGen g)
-> Ord (IOGen g)
IOGen g -> IOGen g -> Bool
IOGen g -> IOGen g -> Ordering
IOGen g -> IOGen g -> IOGen g
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall g. Ord g => Eq (IOGen g)
forall g. Ord g => IOGen g -> IOGen g -> Bool
forall g. Ord g => IOGen g -> IOGen g -> Ordering
forall g. Ord g => IOGen g -> IOGen g -> IOGen g
min :: IOGen g -> IOGen g -> IOGen g
$cmin :: forall g. Ord g => IOGen g -> IOGen g -> IOGen g
max :: IOGen g -> IOGen g -> IOGen g
$cmax :: forall g. Ord g => IOGen g -> IOGen g -> IOGen g
>= :: IOGen g -> IOGen g -> Bool
$c>= :: forall g. Ord g => IOGen g -> IOGen g -> Bool
> :: IOGen g -> IOGen g -> Bool
$c> :: forall g. Ord g => IOGen g -> IOGen g -> Bool
<= :: IOGen g -> IOGen g -> Bool
$c<= :: forall g. Ord g => IOGen g -> IOGen g -> Bool
< :: IOGen g -> IOGen g -> Bool
$c< :: forall g. Ord g => IOGen g -> IOGen g -> Bool
compare :: IOGen g -> IOGen g -> Ordering
$ccompare :: forall g. Ord g => IOGen g -> IOGen g -> Ordering
$cp1Ord :: forall g. Ord g => Eq (IOGen g)
Ord, Int -> IOGen g -> ShowS
[IOGen g] -> ShowS
IOGen g -> String
(Int -> IOGen g -> ShowS)
-> (IOGen g -> String) -> ([IOGen g] -> ShowS) -> Show (IOGen g)
forall g. Show g => Int -> IOGen g -> ShowS
forall g. Show g => [IOGen g] -> ShowS
forall g. Show g => IOGen g -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IOGen g] -> ShowS
$cshowList :: forall g. Show g => [IOGen g] -> ShowS
show :: IOGen g -> String
$cshow :: forall g. Show g => IOGen g -> String
showsPrec :: Int -> IOGen g -> ShowS
$cshowsPrec :: forall g. Show g => Int -> IOGen g -> ShowS
Show, Int -> IOGen g -> (ShortByteString, IOGen g)
Word32 -> IOGen g -> (Word32, IOGen g)
Word64 -> IOGen g -> (Word64, IOGen g)
IOGen g -> (Int, Int)
IOGen g -> (Int, IOGen g)
IOGen g -> (Word8, IOGen g)
IOGen g -> (Word16, IOGen g)
IOGen g -> (Word32, IOGen g)
IOGen g -> (Word64, IOGen g)
IOGen g -> (IOGen g, IOGen g)
(IOGen g -> (Int, IOGen g))
-> (IOGen g -> (Word8, IOGen g))
-> (IOGen g -> (Word16, IOGen g))
-> (IOGen g -> (Word32, IOGen g))
-> (IOGen g -> (Word64, IOGen g))
-> (Word32 -> IOGen g -> (Word32, IOGen g))
-> (Word64 -> IOGen g -> (Word64, IOGen g))
-> (Int -> IOGen g -> (ShortByteString, IOGen g))
-> (IOGen g -> (Int, Int))
-> (IOGen g -> (IOGen g, IOGen g))
-> RandomGen (IOGen g)
forall g.
RandomGen g =>
Int -> IOGen g -> (ShortByteString, IOGen g)
forall g. RandomGen g => Word32 -> IOGen g -> (Word32, IOGen g)
forall g. RandomGen g => Word64 -> IOGen g -> (Word64, IOGen g)
forall g. RandomGen g => IOGen g -> (Int, Int)
forall g. RandomGen g => IOGen g -> (Int, IOGen g)
forall g. RandomGen g => IOGen g -> (Word8, IOGen g)
forall g. RandomGen g => IOGen g -> (Word16, IOGen g)
forall g. RandomGen g => IOGen g -> (Word32, IOGen g)
forall g. RandomGen g => IOGen g -> (Word64, IOGen g)
forall g. RandomGen g => IOGen g -> (IOGen g, IOGen g)
forall g.
(g -> (Int, g))
-> (g -> (Word8, g))
-> (g -> (Word16, g))
-> (g -> (Word32, g))
-> (g -> (Word64, g))
-> (Word32 -> g -> (Word32, g))
-> (Word64 -> g -> (Word64, g))
-> (Int -> g -> (ShortByteString, g))
-> (g -> (Int, Int))
-> (g -> (g, g))
-> RandomGen g
split :: IOGen g -> (IOGen g, IOGen g)
$csplit :: forall g. RandomGen g => IOGen g -> (IOGen g, IOGen g)
genRange :: IOGen g -> (Int, Int)
$cgenRange :: forall g. RandomGen g => IOGen g -> (Int, Int)
genShortByteString :: Int -> IOGen g -> (ShortByteString, IOGen g)
$cgenShortByteString :: forall g.
RandomGen g =>
Int -> IOGen g -> (ShortByteString, IOGen g)
genWord64R :: Word64 -> IOGen g -> (Word64, IOGen g)
$cgenWord64R :: forall g. RandomGen g => Word64 -> IOGen g -> (Word64, IOGen g)
genWord32R :: Word32 -> IOGen g -> (Word32, IOGen g)
$cgenWord32R :: forall g. RandomGen g => Word32 -> IOGen g -> (Word32, IOGen g)
genWord64 :: IOGen g -> (Word64, IOGen g)
$cgenWord64 :: forall g. RandomGen g => IOGen g -> (Word64, IOGen g)
genWord32 :: IOGen g -> (Word32, IOGen g)
$cgenWord32 :: forall g. RandomGen g => IOGen g -> (Word32, IOGen g)
genWord16 :: IOGen g -> (Word16, IOGen g)
$cgenWord16 :: forall g. RandomGen g => IOGen g -> (Word16, IOGen g)
genWord8 :: IOGen g -> (Word8, IOGen g)
$cgenWord8 :: forall g. RandomGen g => IOGen g -> (Word8, IOGen g)
next :: IOGen g -> (Int, IOGen g)
$cnext :: forall g. RandomGen g => IOGen g -> (Int, IOGen g)
RandomGen, Ptr b -> Int -> IO (IOGen g)
Ptr b -> Int -> IOGen g -> IO ()
Ptr (IOGen g) -> IO (IOGen g)
Ptr (IOGen g) -> Int -> IO (IOGen g)
Ptr (IOGen g) -> Int -> IOGen g -> IO ()
Ptr (IOGen g) -> IOGen g -> IO ()
IOGen g -> Int
(IOGen g -> Int)
-> (IOGen g -> Int)
-> (Ptr (IOGen g) -> Int -> IO (IOGen g))
-> (Ptr (IOGen g) -> Int -> IOGen g -> IO ())
-> (forall b. Ptr b -> Int -> IO (IOGen g))
-> (forall b. Ptr b -> Int -> IOGen g -> IO ())
-> (Ptr (IOGen g) -> IO (IOGen g))
-> (Ptr (IOGen g) -> IOGen g -> IO ())
-> Storable (IOGen g)
forall b. Ptr b -> Int -> IO (IOGen g)
forall b. Ptr b -> Int -> IOGen g -> IO ()
forall g. Storable g => Ptr (IOGen g) -> IO (IOGen g)
forall g. Storable g => Ptr (IOGen g) -> Int -> IO (IOGen g)
forall g. Storable g => Ptr (IOGen g) -> Int -> IOGen g -> IO ()
forall g. Storable g => Ptr (IOGen g) -> IOGen g -> IO ()
forall g. Storable g => IOGen g -> Int
forall g b. Storable g => Ptr b -> Int -> IO (IOGen g)
forall g b. Storable g => Ptr b -> Int -> IOGen g -> IO ()
forall a.
(a -> Int)
-> (a -> Int)
-> (Ptr a -> Int -> IO a)
-> (Ptr a -> Int -> a -> IO ())
-> (forall b. Ptr b -> Int -> IO a)
-> (forall b. Ptr b -> Int -> a -> IO ())
-> (Ptr a -> IO a)
-> (Ptr a -> a -> IO ())
-> Storable a
poke :: Ptr (IOGen g) -> IOGen g -> IO ()
$cpoke :: forall g. Storable g => Ptr (IOGen g) -> IOGen g -> IO ()
peek :: Ptr (IOGen g) -> IO (IOGen g)
$cpeek :: forall g. Storable g => Ptr (IOGen g) -> IO (IOGen g)
pokeByteOff :: Ptr b -> Int -> IOGen g -> IO ()
$cpokeByteOff :: forall g b. Storable g => Ptr b -> Int -> IOGen g -> IO ()
peekByteOff :: Ptr b -> Int -> IO (IOGen g)
$cpeekByteOff :: forall g b. Storable g => Ptr b -> Int -> IO (IOGen g)
pokeElemOff :: Ptr (IOGen g) -> Int -> IOGen g -> IO ()
$cpokeElemOff :: forall g. Storable g => Ptr (IOGen g) -> Int -> IOGen g -> IO ()
peekElemOff :: Ptr (IOGen g) -> Int -> IO (IOGen g)
$cpeekElemOff :: forall g. Storable g => Ptr (IOGen g) -> Int -> IO (IOGen g)
alignment :: IOGen g -> Int
$calignment :: forall g. Storable g => IOGen g -> Int
sizeOf :: IOGen g -> Int
$csizeOf :: forall g. Storable g => IOGen g -> Int
Storable, IOGen g -> ()
(IOGen g -> ()) -> NFData (IOGen g)
forall g. NFData g => IOGen g -> ()
forall a. (a -> ()) -> NFData a
rnf :: IOGen g -> ()
$crnf :: forall g. NFData g => IOGen g -> ()
NFData)


-- | Creates a new 'IOGenM'.
--
-- @since 1.2.0
newIOGenM :: MonadIO m => g -> m (IOGenM g)
newIOGenM :: g -> m (IOGenM g)
newIOGenM = (IORef g -> IOGenM g) -> m (IORef g) -> m (IOGenM g)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap IORef g -> IOGenM g
forall g. IORef g -> IOGenM g
IOGenM (m (IORef g) -> m (IOGenM g))
-> (g -> m (IORef g)) -> g -> m (IOGenM g)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (IORef g) -> m (IORef g)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (IORef g) -> m (IORef g))
-> (g -> IO (IORef g)) -> g -> m (IORef g)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. g -> IO (IORef g)
forall a. a -> IO (IORef a)
newIORef

instance (RandomGen g, MonadIO m) => StatefulGen (IOGenM g) m where
  uniformWord32R :: Word32 -> IOGenM g -> m Word32
uniformWord32R Word32
r = (g -> (Word32, g)) -> IOGenM g -> m Word32
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> IOGenM g -> m a
applyIOGen (Word32 -> g -> (Word32, g)
forall g. RandomGen g => Word32 -> g -> (Word32, g)
genWord32R Word32
r)
  {-# INLINE uniformWord32R #-}
  uniformWord64R :: Word64 -> IOGenM g -> m Word64
uniformWord64R Word64
r = (g -> (Word64, g)) -> IOGenM g -> m Word64
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> IOGenM g -> m a
applyIOGen (Word64 -> g -> (Word64, g)
forall g. RandomGen g => Word64 -> g -> (Word64, g)
genWord64R Word64
r)
  {-# INLINE uniformWord64R #-}
  uniformWord8 :: IOGenM g -> m Word8
uniformWord8 = (g -> (Word8, g)) -> IOGenM g -> m Word8
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> IOGenM g -> m a
applyIOGen g -> (Word8, g)
forall g. RandomGen g => g -> (Word8, g)
genWord8
  {-# INLINE uniformWord8 #-}
  uniformWord16 :: IOGenM g -> m Word16
uniformWord16 = (g -> (Word16, g)) -> IOGenM g -> m Word16
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> IOGenM g -> m a
applyIOGen g -> (Word16, g)
forall g. RandomGen g => g -> (Word16, g)
genWord16
  {-# INLINE uniformWord16 #-}
  uniformWord32 :: IOGenM g -> m Word32
uniformWord32 = (g -> (Word32, g)) -> IOGenM g -> m Word32
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> IOGenM g -> m a
applyIOGen g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
genWord32
  {-# INLINE uniformWord32 #-}
  uniformWord64 :: IOGenM g -> m Word64
uniformWord64 = (g -> (Word64, g)) -> IOGenM g -> m Word64
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> IOGenM g -> m a
applyIOGen g -> (Word64, g)
forall g. RandomGen g => g -> (Word64, g)
genWord64
  {-# INLINE uniformWord64 #-}
  uniformShortByteString :: Int -> IOGenM g -> m ShortByteString
uniformShortByteString Int
n = (g -> (ShortByteString, g)) -> IOGenM g -> m ShortByteString
forall (m :: * -> *) g a.
MonadIO m =>
(g -> (a, g)) -> IOGenM g -> m a
applyIOGen (Int -> g -> (ShortByteString, g)
forall g. RandomGen g => Int -> g -> (ShortByteString, g)
genShortByteString Int
n)


instance (RandomGen g, MonadIO m) => FrozenGen (IOGen g) m where
  type MutableGen (IOGen g) m = IOGenM g
  freezeGen :: MutableGen (IOGen g) m -> m (IOGen g)
freezeGen = (g -> IOGen g) -> m g -> m (IOGen g)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap g -> IOGen g
forall g. g -> IOGen g
IOGen (m g -> m (IOGen g))
-> (IOGenM g -> m g) -> IOGenM g -> m (IOGen g)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO g -> m g
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO g -> m g) -> (IOGenM g -> IO g) -> IOGenM g -> m g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IORef g -> IO g
forall a. IORef a -> IO a
readIORef (IORef g -> IO g) -> (IOGenM g -> IORef g) -> IOGenM g -> IO g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IOGenM g -> IORef g
forall g. IOGenM g -> IORef g
unIOGenM
  thawGen :: IOGen g -> m (MutableGen (IOGen g) m)
thawGen (IOGen g
g) = g -> m (IOGenM g)
forall (m :: * -> *) g. MonadIO m => g -> m (IOGenM g)
newIOGenM g
g


-- | Applies a pure operation to the wrapped pseudo-random number generator.
--
-- ====__Examples__
--
-- >>> import System.Random.Stateful
-- >>> let pureGen = mkStdGen 137
-- >>> g <- newIOGenM pureGen
-- >>> applyIOGen random g :: IO Int
-- 7879794327570578227
--
-- @since 1.2.0
applyIOGen :: MonadIO m => (g -> (a, g)) -> IOGenM g -> m a
applyIOGen :: (g -> (a, g)) -> IOGenM g -> m a
applyIOGen g -> (a, g)
f (IOGenM IORef g
ref) = IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ do
  g
g <- IORef g -> IO g
forall a. IORef a -> IO a
readIORef IORef g
ref
  case g -> (a, g)
f g
g of
    (!a
a, !g
g') -> a
a a -> IO () -> IO a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ IORef g -> g -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef g
ref g
g'
{-# INLINE applyIOGen #-}

-- | Wraps an 'STRef' that holds a pure pseudo-random number generator.
--
-- *   'STGenM' is safe in the presence of exceptions, but not concurrency.
-- *   'STGenM' is slower than 'StateGenM' due to the extra pointer indirection.
--
-- @since 1.2.0
newtype STGenM g s = STGenM { STGenM g s -> STRef s g
unSTGenM :: STRef s g }

-- | Frozen version of mutable `STGenM` generator
--
-- @since 1.2.0
newtype STGen g = STGen { STGen g -> g
unSTGen :: g }
  deriving (STGen g -> STGen g -> Bool
(STGen g -> STGen g -> Bool)
-> (STGen g -> STGen g -> Bool) -> Eq (STGen g)
forall g. Eq g => STGen g -> STGen g -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: STGen g -> STGen g -> Bool
$c/= :: forall g. Eq g => STGen g -> STGen g -> Bool
== :: STGen g -> STGen g -> Bool
$c== :: forall g. Eq g => STGen g -> STGen g -> Bool
Eq, Eq (STGen g)
Eq (STGen g)
-> (STGen g -> STGen g -> Ordering)
-> (STGen g -> STGen g -> Bool)
-> (STGen g -> STGen g -> Bool)
-> (STGen g -> STGen g -> Bool)
-> (STGen g -> STGen g -> Bool)
-> (STGen g -> STGen g -> STGen g)
-> (STGen g -> STGen g -> STGen g)
-> Ord (STGen g)
STGen g -> STGen g -> Bool
STGen g -> STGen g -> Ordering
STGen g -> STGen g -> STGen g
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall g. Ord g => Eq (STGen g)
forall g. Ord g => STGen g -> STGen g -> Bool
forall g. Ord g => STGen g -> STGen g -> Ordering
forall g. Ord g => STGen g -> STGen g -> STGen g
min :: STGen g -> STGen g -> STGen g
$cmin :: forall g. Ord g => STGen g -> STGen g -> STGen g
max :: STGen g -> STGen g -> STGen g
$cmax :: forall g. Ord g => STGen g -> STGen g -> STGen g
>= :: STGen g -> STGen g -> Bool
$c>= :: forall g. Ord g => STGen g -> STGen g -> Bool
> :: STGen g -> STGen g -> Bool
$c> :: forall g. Ord g => STGen g -> STGen g -> Bool
<= :: STGen g -> STGen g -> Bool
$c<= :: forall g. Ord g => STGen g -> STGen g -> Bool
< :: STGen g -> STGen g -> Bool
$c< :: forall g. Ord g => STGen g -> STGen g -> Bool
compare :: STGen g -> STGen g -> Ordering
$ccompare :: forall g. Ord g => STGen g -> STGen g -> Ordering
$cp1Ord :: forall g. Ord g => Eq (STGen g)
Ord, Int -> STGen g -> ShowS
[STGen g] -> ShowS
STGen g -> String
(Int -> STGen g -> ShowS)
-> (STGen g -> String) -> ([STGen g] -> ShowS) -> Show (STGen g)
forall g. Show g => Int -> STGen g -> ShowS
forall g. Show g => [STGen g] -> ShowS
forall g. Show g => STGen g -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [STGen g] -> ShowS
$cshowList :: forall g. Show g => [STGen g] -> ShowS
show :: STGen g -> String
$cshow :: forall g. Show g => STGen g -> String
showsPrec :: Int -> STGen g -> ShowS
$cshowsPrec :: forall g. Show g => Int -> STGen g -> ShowS
Show, Int -> STGen g -> (ShortByteString, STGen g)
Word32 -> STGen g -> (Word32, STGen g)
Word64 -> STGen g -> (Word64, STGen g)
STGen g -> (Int, Int)
STGen g -> (Int, STGen g)
STGen g -> (Word8, STGen g)
STGen g -> (Word16, STGen g)
STGen g -> (Word32, STGen g)
STGen g -> (Word64, STGen g)
STGen g -> (STGen g, STGen g)
(STGen g -> (Int, STGen g))
-> (STGen g -> (Word8, STGen g))
-> (STGen g -> (Word16, STGen g))
-> (STGen g -> (Word32, STGen g))
-> (STGen g -> (Word64, STGen g))
-> (Word32 -> STGen g -> (Word32, STGen g))
-> (Word64 -> STGen g -> (Word64, STGen g))
-> (Int -> STGen g -> (ShortByteString, STGen g))
-> (STGen g -> (Int, Int))
-> (STGen g -> (STGen g, STGen g))
-> RandomGen (STGen g)
forall g.
RandomGen g =>
Int -> STGen g -> (ShortByteString, STGen g)
forall g. RandomGen g => Word32 -> STGen g -> (Word32, STGen g)
forall g. RandomGen g => Word64 -> STGen g -> (Word64, STGen g)
forall g. RandomGen g => STGen g -> (Int, Int)
forall g. RandomGen g => STGen g -> (Int, STGen g)
forall g. RandomGen g => STGen g -> (Word8, STGen g)
forall g. RandomGen g => STGen g -> (Word16, STGen g)
forall g. RandomGen g => STGen g -> (Word32, STGen g)
forall g. RandomGen g => STGen g -> (Word64, STGen g)
forall g. RandomGen g => STGen g -> (STGen g, STGen g)
forall g.
(g -> (Int, g))
-> (g -> (Word8, g))
-> (g -> (Word16, g))
-> (g -> (Word32, g))
-> (g -> (Word64, g))
-> (Word32 -> g -> (Word32, g))
-> (Word64 -> g -> (Word64, g))
-> (Int -> g -> (ShortByteString, g))
-> (g -> (Int, Int))
-> (g -> (g, g))
-> RandomGen g
split :: STGen g -> (STGen g, STGen g)
$csplit :: forall g. RandomGen g => STGen g -> (STGen g, STGen g)
genRange :: STGen g -> (Int, Int)
$cgenRange :: forall g. RandomGen g => STGen g -> (Int, Int)
genShortByteString :: Int -> STGen g -> (ShortByteString, STGen g)
$cgenShortByteString :: forall g.
RandomGen g =>
Int -> STGen g -> (ShortByteString, STGen g)
genWord64R :: Word64 -> STGen g -> (Word64, STGen g)
$cgenWord64R :: forall g. RandomGen g => Word64 -> STGen g -> (Word64, STGen g)
genWord32R :: Word32 -> STGen g -> (Word32, STGen g)
$cgenWord32R :: forall g. RandomGen g => Word32 -> STGen g -> (Word32, STGen g)
genWord64 :: STGen g -> (Word64, STGen g)
$cgenWord64 :: forall g. RandomGen g => STGen g -> (Word64, STGen g)
genWord32 :: STGen g -> (Word32, STGen g)
$cgenWord32 :: forall g. RandomGen g => STGen g -> (Word32, STGen g)
genWord16 :: STGen g -> (Word16, STGen g)
$cgenWord16 :: forall g. RandomGen g => STGen g -> (Word16, STGen g)
genWord8 :: STGen g -> (Word8, STGen g)
$cgenWord8 :: forall g. RandomGen g => STGen g -> (Word8, STGen g)
next :: STGen g -> (Int, STGen g)
$cnext :: forall g. RandomGen g => STGen g -> (Int, STGen g)
RandomGen, Ptr b -> Int -> IO (STGen g)
Ptr b -> Int -> STGen g -> IO ()
Ptr (STGen g) -> IO (STGen g)
Ptr (STGen g) -> Int -> IO (STGen g)
Ptr (STGen g) -> Int -> STGen g -> IO ()
Ptr (STGen g) -> STGen g -> IO ()
STGen g -> Int
(STGen g -> Int)
-> (STGen g -> Int)
-> (Ptr (STGen g) -> Int -> IO (STGen g))
-> (Ptr (STGen g) -> Int -> STGen g -> IO ())
-> (forall b. Ptr b -> Int -> IO (STGen g))
-> (forall b. Ptr b -> Int -> STGen g -> IO ())
-> (Ptr (STGen g) -> IO (STGen g))
-> (Ptr (STGen g) -> STGen g -> IO ())
-> Storable (STGen g)
forall b. Ptr b -> Int -> IO (STGen g)
forall b. Ptr b -> Int -> STGen g -> IO ()
forall g. Storable g => Ptr (STGen g) -> IO (STGen g)
forall g. Storable g => Ptr (STGen g) -> Int -> IO (STGen g)
forall g. Storable g => Ptr (STGen g) -> Int -> STGen g -> IO ()
forall g. Storable g => Ptr (STGen g) -> STGen g -> IO ()
forall g. Storable g => STGen g -> Int
forall g b. Storable g => Ptr b -> Int -> IO (STGen g)
forall g b. Storable g => Ptr b -> Int -> STGen g -> IO ()
forall a.
(a -> Int)
-> (a -> Int)
-> (Ptr a -> Int -> IO a)
-> (Ptr a -> Int -> a -> IO ())
-> (forall b. Ptr b -> Int -> IO a)
-> (forall b. Ptr b -> Int -> a -> IO ())
-> (Ptr a -> IO a)
-> (Ptr a -> a -> IO ())
-> Storable a
poke :: Ptr (STGen g) -> STGen g -> IO ()
$cpoke :: forall g. Storable g => Ptr (STGen g) -> STGen g -> IO ()
peek :: Ptr (STGen g) -> IO (STGen g)
$cpeek :: forall g. Storable g => Ptr (STGen g) -> IO (STGen g)
pokeByteOff :: Ptr b -> Int -> STGen g -> IO ()
$cpokeByteOff :: forall g b. Storable g => Ptr b -> Int -> STGen g -> IO ()
peekByteOff :: Ptr b -> Int -> IO (STGen g)
$cpeekByteOff :: forall g b. Storable g => Ptr b -> Int -> IO (STGen g)
pokeElemOff :: Ptr (STGen g) -> Int -> STGen g -> IO ()
$cpokeElemOff :: forall g. Storable g => Ptr (STGen g) -> Int -> STGen g -> IO ()
peekElemOff :: Ptr (STGen g) -> Int -> IO (STGen g)
$cpeekElemOff :: forall g. Storable g => Ptr (STGen g) -> Int -> IO (STGen g)
alignment :: STGen g -> Int
$calignment :: forall g. Storable g => STGen g -> Int
sizeOf :: STGen g -> Int
$csizeOf :: forall g. Storable g => STGen g -> Int
Storable, STGen g -> ()
(STGen g -> ()) -> NFData (STGen g)
forall g. NFData g => STGen g -> ()
forall a. (a -> ()) -> NFData a
rnf :: STGen g -> ()
$crnf :: forall g. NFData g => STGen g -> ()
NFData)

-- | Creates a new 'STGenM'.
--
-- @since 1.2.0
newSTGenM :: g -> ST s (STGenM g s)
newSTGenM :: g -> ST s (STGenM g s)
newSTGenM = (STRef s g -> STGenM g s) -> ST s (STRef s g) -> ST s (STGenM g s)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap STRef s g -> STGenM g s
forall g s. STRef s g -> STGenM g s
STGenM (ST s (STRef s g) -> ST s (STGenM g s))
-> (g -> ST s (STRef s g)) -> g -> ST s (STGenM g s)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. g -> ST s (STRef s g)
forall a s. a -> ST s (STRef s a)
newSTRef


instance RandomGen g => StatefulGen (STGenM g s) (ST s) where
  uniformWord32R :: Word32 -> STGenM g s -> ST s Word32
uniformWord32R Word32
r = (g -> (Word32, g)) -> STGenM g s -> ST s Word32
forall g a s. (g -> (a, g)) -> STGenM g s -> ST s a
applySTGen (Word32 -> g -> (Word32, g)
forall g. RandomGen g => Word32 -> g -> (Word32, g)
genWord32R Word32
r)
  {-# INLINE uniformWord32R #-}
  uniformWord64R :: Word64 -> STGenM g s -> ST s Word64
uniformWord64R Word64
r = (g -> (Word64, g)) -> STGenM g s -> ST s Word64
forall g a s. (g -> (a, g)) -> STGenM g s -> ST s a
applySTGen (Word64 -> g -> (Word64, g)
forall g. RandomGen g => Word64 -> g -> (Word64, g)
genWord64R Word64
r)
  {-# INLINE uniformWord64R #-}
  uniformWord8 :: STGenM g s -> ST s Word8
uniformWord8 = (g -> (Word8, g)) -> STGenM g s -> ST s Word8
forall g a s. (g -> (a, g)) -> STGenM g s -> ST s a
applySTGen g -> (Word8, g)
forall g. RandomGen g => g -> (Word8, g)
genWord8
  {-# INLINE uniformWord8 #-}
  uniformWord16 :: STGenM g s -> ST s Word16
uniformWord16 = (g -> (Word16, g)) -> STGenM g s -> ST s Word16
forall g a s. (g -> (a, g)) -> STGenM g s -> ST s a
applySTGen g -> (Word16, g)
forall g. RandomGen g => g -> (Word16, g)
genWord16
  {-# INLINE uniformWord16 #-}
  uniformWord32 :: STGenM g s -> ST s Word32
uniformWord32 = (g -> (Word32, g)) -> STGenM g s -> ST s Word32
forall g a s. (g -> (a, g)) -> STGenM g s -> ST s a
applySTGen g -> (Word32, g)
forall g. RandomGen g => g -> (Word32, g)
genWord32
  {-# INLINE uniformWord32 #-}
  uniformWord64 :: STGenM g s -> ST s Word64
uniformWord64 = (g -> (Word64, g)) -> STGenM g s -> ST s Word64
forall g a s. (g -> (a, g)) -> STGenM g s -> ST s a
applySTGen g -> (Word64, g)
forall g. RandomGen g => g -> (Word64, g)
genWord64
  {-# INLINE uniformWord64 #-}
  uniformShortByteString :: Int -> STGenM g s -> ST s ShortByteString
uniformShortByteString Int
n = (g -> (ShortByteString, g)) -> STGenM g s -> ST s ShortByteString
forall g a s. (g -> (a, g)) -> STGenM g s -> ST s a
applySTGen (Int -> g -> (ShortByteString, g)
forall g. RandomGen g => Int -> g -> (ShortByteString, g)
genShortByteString Int
n)

instance RandomGen g => FrozenGen (STGen g) (ST s) where
  type MutableGen (STGen g) (ST s) = STGenM g s
  freezeGen :: MutableGen (STGen g) (ST s) -> ST s (STGen g)
freezeGen = (g -> STGen g) -> ST s g -> ST s (STGen g)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap g -> STGen g
forall g. g -> STGen g
STGen (ST s g -> ST s (STGen g))
-> (STGenM g s -> ST s g) -> STGenM g s -> ST s (STGen g)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. STRef s g -> ST s g
forall s a. STRef s a -> ST s a
readSTRef (STRef s g -> ST s g)
-> (STGenM g s -> STRef s g) -> STGenM g s -> ST s g
forall b c a. (b -> c) -> (a -> b) -> a -> c
. STGenM g s -> STRef s g
forall g s. STGenM g s -> STRef s g
unSTGenM
  thawGen :: STGen g -> ST s (MutableGen (STGen g) (ST s))
thawGen (STGen g
g) = g -> ST s (STGenM g s)
forall g s. g -> ST s (STGenM g s)
newSTGenM g
g


-- | Applies a pure operation to the wrapped pseudo-random number generator.
--
-- ====__Examples__
--
-- >>> import System.Random.Stateful
-- >>> let pureGen = mkStdGen 137
-- >>> (runSTGen pureGen (\g -> applySTGen random g)) :: (Int, StdGen)
-- (7879794327570578227,StdGen {unStdGen = SMGen 11285859549637045894 7641485672361121627})
--
-- @since 1.2.0
applySTGen :: (g -> (a, g)) -> STGenM g s -> ST s a
applySTGen :: (g -> (a, g)) -> STGenM g s -> ST s a
applySTGen g -> (a, g)
f (STGenM STRef s g
ref) = do
  g
g <- STRef s g -> ST s g
forall s a. STRef s a -> ST s a
readSTRef STRef s g
ref
  case g -> (a, g)
f g
g of
    (!a
a, !g
g') -> a
a a -> ST s () -> ST s a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ STRef s g -> g -> ST s ()
forall s a. STRef s a -> a -> ST s ()
writeSTRef STRef s g
ref g
g'
{-# INLINE applySTGen #-}

-- | Runs a monadic generating action in the `ST` monad using a pure
-- pseudo-random number generator.
--
-- ====__Examples__
--
-- >>> import System.Random.Stateful
-- >>> let pureGen = mkStdGen 137
-- >>> (runSTGen pureGen (\g -> applySTGen random g)) :: (Int, StdGen)
-- (7879794327570578227,StdGen {unStdGen = SMGen 11285859549637045894 7641485672361121627})
--
-- @since 1.2.0
runSTGen :: RandomGen g => g -> (forall s . STGenM g s -> ST s a) -> (a, g)
runSTGen :: g -> (forall s. STGenM g s -> ST s a) -> (a, g)
runSTGen g
g forall s. STGenM g s -> ST s a
action = STGen g -> g
forall g. STGen g -> g
unSTGen (STGen g -> g) -> (a, STGen g) -> (a, g)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall s. ST s (a, STGen g)) -> (a, STGen g)
forall a. (forall s. ST s a) -> a
runST (STGen g
-> (MutableGen (STGen g) (ST s) -> ST s a) -> ST s (a, STGen g)
forall f (m :: * -> *) a.
FrozenGen f m =>
f -> (MutableGen f m -> m a) -> m (a, f)
withMutableGen (g -> STGen g
forall g. g -> STGen g
STGen g
g) MutableGen (STGen g) (ST s) -> ST s a
forall s. STGenM g s -> ST s a
action)

-- | Runs a monadic generating action in the `ST` monad using a pure
-- pseudo-random number generator. Returns only the resulting pseudo-random
-- value.
--
-- ====__Examples__
--
-- >>> import System.Random.Stateful
-- >>> let pureGen = mkStdGen 137
-- >>> (runSTGen_ pureGen (\g -> applySTGen random g)) :: Int
-- 7879794327570578227
--
-- @since 1.2.0
runSTGen_ :: RandomGen g => g -> (forall s . STGenM g s -> ST s a) -> a
runSTGen_ :: g -> (forall s. STGenM g s -> ST s a) -> a
runSTGen_ g
g forall s. STGenM g s -> ST s a
action = (a, g) -> a
forall a b. (a, b) -> a
fst ((a, g) -> a) -> (a, g) -> a
forall a b. (a -> b) -> a -> b
$ g -> (forall s. STGenM g s -> ST s a) -> (a, g)
forall g a.
RandomGen g =>
g -> (forall s. STGenM g s -> ST s a) -> (a, g)
runSTGen g
g forall s. STGenM g s -> ST s a
action


-- $uniform
--
-- This library provides two type classes to generate pseudo-random values:
--
-- *   'UniformRange' is used to generate a value of a type uniformly within a
--     range.
-- *   'Uniform' is used to generate a value of a type uniformly over all
--     possible values of that type.
--
-- Types may have instances for both or just one of 'UniformRange' and
-- 'Uniform'. A few examples illustrate this:
--
-- *   'Int', 'Word16' and 'Bool' are instances of both 'UniformRange' and
--     'Uniform'.
-- *   'Integer', 'Float' and 'Double' each have an instance for 'UniformRange'
--     but no 'Uniform' instance.
-- *   A hypothetical type @Radian@ representing angles by taking values in the
--     range @[0, 2π)@ has a trivial 'Uniform' instance, but no 'UniformRange'
--     instance: the problem is that two given @Radian@ values always span /two/
--     ranges, one clockwise and one anti-clockwise.
-- *   It is trivial to construct a @Uniform (a, b)@ instance given
--     @Uniform a@ and @Uniform b@ (and this library provides this tuple
--     instance).
-- *   On the other hand, there is no correct way to construct a
--     @UniformRange (a, b)@ instance based on just @UniformRange a@ and
--     @UniformRange b@.

-------------------------------------------------------------------------------
-- Notes
-------------------------------------------------------------------------------

-- $floating
--
-- The 'UniformRange' instances for 'Float' and 'Double' use the following
-- procedure to generate a random value in a range for @uniformRM (a, b) g@:
--
-- If \(a = b\), return \(a\). Otherwise:
--
-- 1.  Generate \(x\) uniformly such that \(0 \leq x \leq 1\).
--
--     The method by which \(x\) is sampled does not cover all representable
--     floating point numbers in the unit interval. The method never generates
--     denormal floating point numbers, for example.
--
-- 2.  Return \(x \cdot a + (1 - x) \cdot b\).
--
--     Due to rounding errors, floating point operations are neither
--     associative nor distributive the way the corresponding operations on
--     real numbers are. Additionally, floating point numbers admit special
--     values @NaN@ as well as negative and positive infinity.
--
-- For pathological values, step 2 can yield surprising results.
--
-- *   The result may be greater than @max a b@.
--
--     >>> :{
--     let (a, b, x) = (-2.13238e-29, -2.1323799e-29, 0.27736077)
--         result = x * a + (1 - x) * b :: Float
--     in (result, result > max a b)
--     :}
--     (-2.1323797e-29,True)
--
-- *   The result may be smaller than @min a b@.
--
--     >>> :{
--     let (a, b, x) = (-1.9087862, -1.908786, 0.4228573)
--         result = x * a + (1 - x) * b :: Float
--     in (result, result < min a b)
--     :}
--     (-1.9087863,True)
--
-- What happens when @NaN@ or @Infinity@ are given to 'uniformRM'? We first
-- define them as constants:
--
-- >>> nan = read "NaN" :: Float
-- >>> inf = read "Infinity" :: Float
--
-- *   If at least one of \(a\) or \(b\) is @NaN@, the result is @NaN@.
--
--     >>> let (a, b, x) = (nan, 1, 0.5) in x * a + (1 - x) * b
--     NaN
--     >>> let (a, b, x) = (-1, nan, 0.5) in x * a + (1 - x) * b
--     NaN
--
-- *   If \(a\) is @-Infinity@ and \(b\) is @Infinity@, the result is @NaN@.
--     >>> let (a, b, x) = (-inf, inf, 0.5) in x * a + (1 - x) * b
--     NaN
--
-- *   Otherwise, if \(a\) is @Infinity@ or @-Infinity@, the result is \(a\).
--
--     >>> let (a, b, x) = (inf, 1, 0.5) in x * a + (1 - x) * b
--     Infinity
--     >>> let (a, b, x) = (-inf, 1, 0.5) in x * a + (1 - x) * b
--     -Infinity
--
-- *   Otherwise, if \(b\) is @Infinity@ or @-Infinity@, the result is \(b\).
--
--     >>> let (a, b, x) = (1, inf, 0.5) in x * a + (1 - x) * b
--     Infinity
--     >>> let (a, b, x) = (1, -inf, 0.5) in x * a + (1 - x) * b
--     -Infinity
--
-- Note that the [GCC 10.1.0 C++ standard library](https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/include/bits/random.h;h=19307fbc3ca401976ef6823e8fda893e4a263751;hb=63fa67847628e5f358e7e2e7edb8314f0ee31f30#l1859),
-- the [Java 10 standard library](https://docs.oracle.com/javase/10/docs/api/java/util/Random.html#doubles%28double,double%29)
-- and [CPython 3.8](https://github.com/python/cpython/blob/3.8/Lib/random.py#L417)
-- use the same procedure to generate floating point values in a range.
--
-- $implementmonadrandom
--
-- Typically, a monadic pseudo-random number generator has facilities to save
-- and restore its internal state in addition to generating pseudo-random numbers.
--
-- Here is an example instance for the monadic pseudo-random number generator
-- from the @mwc-random@ package:
--
-- > instance (s ~ PrimState m, PrimMonad m) => StatefulGen (MWC.Gen s) m where
-- >   uniformWord8 = MWC.uniform
-- >   uniformWord16 = MWC.uniform
-- >   uniformWord32 = MWC.uniform
-- >   uniformWord64 = MWC.uniform
-- >   uniformShortByteString n g = unsafeSTToPrim (genShortByteStringST n (MWC.uniform g))
--
-- > instance PrimMonad m => FrozenGen MWC.Seed m where
-- >   type MutableGen MWC.Seed m = MWC.Gen (PrimState m)
-- >   thawGen = MWC.restore
-- >   freezeGen = MWC.save
--
-- === @FrozenGen@
--
-- `FrozenGen` gives us ability to use any stateful pseudo-random number generator in its
-- immutable form, if one exists that is. This concept is commonly known as a seed, which
-- allows us to save and restore the actual mutable state of a pseudo-random number
-- generator. The biggest benefit that can be drawn from a polymorphic access to a
-- stateful pseudo-random number generator in a frozen form is the ability to serialize,
-- deserialize and possibly even use the stateful generator in a pure setting without
-- knowing the actual type of a generator ahead of time. For example we can write a
-- function that accepts a frozen state of some pseudo-random number generator and
-- produces a short list with random even integers.
--
-- >>> import Data.Int (Int8)
-- >>> :{
-- myCustomRandomList :: FrozenGen f m => f -> m [Int8]
-- myCustomRandomList f =
--   withMutableGen_ f $ \gen -> do
--     len <- uniformRM (5, 10) gen
--     replicateM len $ do
--       x <- uniformM gen
--       pure $ if even x then x else x + 1
-- :}
--
-- and later we can apply it to a frozen version of a stateful generator, such as `STGen`:
--
-- >>> print $ runST $ myCustomRandomList (STGen (mkStdGen 217))
-- [-50,-2,4,-8,-58,-40,24,-32,-110,24]
--
-- or a @Seed@ from @mwc-random@:
--
-- >>> import Data.Vector.Primitive as P
-- >>> print $ runST $ myCustomRandomList (MWC.toSeed (P.fromList [1,2,3]))
-- [24,40,10,40,-8,48,-78,70,-12]
--
-- Alternatively, instead of discarding the final state of the generator, as it happens
-- above, we could have used `withMutableGen`, which together with the result would give
-- us back its frozen form. This would allow us to store the end state of our generator
-- somewhere for the later reuse.
--
--
-- $references
--
-- 1. Guy L. Steele, Jr., Doug Lea, and Christine H. Flood. 2014. Fast
-- splittable pseudorandom number generators. In Proceedings of the 2014 ACM
-- International Conference on Object Oriented Programming Systems Languages &
-- Applications (OOPSLA '14). ACM, New York, NY, USA, 453-472. DOI:
-- <https://doi.org/10.1145/2660193.2660195>

-- $setup
-- >>> import Control.Monad.Primitive
-- >>> import qualified System.Random.MWC as MWC
--
-- >>> :set -XFlexibleContexts
-- >>> :set -XFlexibleInstances
-- >>> :set -XMultiParamTypeClasses
-- >>> :set -XTypeFamilies
-- >>> :set -XUndecidableInstances
--
-- >>> :{
-- instance (s ~ PrimState m, PrimMonad m) => StatefulGen (MWC.Gen s) m where
--   uniformWord8 = MWC.uniform
--   uniformWord16 = MWC.uniform
--   uniformWord32 = MWC.uniform
--   uniformWord64 = MWC.uniform
--   uniformShortByteString n g = unsafeSTToPrim (genShortByteStringST n (MWC.uniform g))
-- instance PrimMonad m => FrozenGen MWC.Seed m where
--   type MutableGen MWC.Seed m = MWC.Gen (PrimState m)
--   thawGen = MWC.restore
--   freezeGen = MWC.save
-- :}
--