Skip to content

Commit

Permalink
Refactor MonadRandom -> StatefulGen. Rename Random.Monad -> Random.St…
Browse files Browse the repository at this point in the history
…ateful
  • Loading branch information
lehins committed Jun 4, 2020
1 parent 02d4201 commit 78e0f84
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 55 deletions.
2 changes: 1 addition & 1 deletion bench/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import Gauge.Main
import Numeric.Natural (Natural)
import System.Random.SplitMix as SM

import System.Random.Monad
import System.Random.Stateful

main :: IO ()
main = do
Expand Down
16 changes: 8 additions & 8 deletions random.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,24 @@ description:
.
See "System.Random" for more details.
.
== "System.Random.Monad": monadic pseudo-random number interface
== "System.Random.Stateful": monadic pseudo-random number interface
.
In monadic code, use 'System.Random.Monad.uniformM' and
'System.Random.Monad.uniformRM' from "System.Random.Monad" to generate
In monadic code, use 'System.Random.Stateful.uniformM' and
'System.Random.Stateful.uniformRM' from "System.Random.Stateful" to generate
pseudo-random numbers with a monadic pseudo-random number generator, or
using a monadic adapter.
.
As an example, here is how you can simulate rolls of a six-sided die using
'System.Random.Monad.uniformRM':
'System.Random.Stateful.uniformRM':
.
>>> let rollM = uniformRM (1, 6) :: MonadRandom g s m => g s -> m Word8
>>> let pureGen = mkStdGen 42
>>> runGenState_ pureGen (replicateM 10 . rollM) :: m [Word8]
[1,1,3,2,4,5,3,4,6,2]
.
The monadic adapter 'System.Random.Monad.runGenState_' is used here to lift
The monadic adapter 'System.Random.Stateful.runGenState_' is used here to lift
the pure pseudo-random number generator @pureGen@ into the
'System.Random.Monad.MonadRandom' context.
'System.Random.Stateful.MonadRandom' context.
.
The monadic interface can also be used with existing monadic pseudo-random
number generators. In this example, we use the one provided in the
Expand All @@ -56,7 +56,7 @@ description:
>>> (replicateM 10 . rollM) monadicGen :: m [Word8]
[2,3,6,6,4,4,3,1,5,4]
.
See "System.Random.Monad" for more details.
See "System.Random.Stateful" for more details.

category: System
build-type: Custom
Expand All @@ -78,7 +78,7 @@ library
exposed-modules:
System.Random
System.Random.Internal
System.Random.Monad
System.Random.Stateful

hs-source-dirs: src
default-language: Haskell2010
Expand Down
10 changes: 5 additions & 5 deletions src/System/Random.hs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ import qualified System.Random.SplitMix as SM
-- pseudo-random number generator, use 'runGenState' and its variants.
--
-- >>> :{
-- let rollsM :: MonadRandom g m => Int -> g -> m [Word8]
-- let rollsM :: StatefulGen g m => Int -> g -> m [Word8]
-- rollsM n = replicateM n . uniformRM (1, 6)
-- pureGen = mkStdGen 137
-- in
Expand All @@ -123,14 +123,14 @@ import qualified System.Random.SplitMix as SM
-- produced by the two resulting generators are not correlated. See [1] for
-- some background on splittable pseudo-random generators.
--
-- ['System.Random.Monad.MonadRandom': monadic pseudo-random number generators]
-- See "System.Random.Monad" module
-- ['System.Random.Stateful.StatefulGen': monadic pseudo-random number generators]
-- See "System.Random.Stateful" module
--

-- | Generates a value uniformly distributed over all possible values of that
-- type.
--
-- This is a pure version of 'System.Random.Monad.uniformM'.
-- This is a pure version of 'System.Random.Stateful.uniformM'.
--
-- @since 1.2
uniform :: (RandomGen g, Uniform a) => g -> (a, g)
Expand All @@ -149,7 +149,7 @@ uniform g = runStateGen g uniformM
--
-- > uniformR (a, b) = uniformR (b, a)
--
-- This is a pure version of 'System.Random.Monad.uniformRM'.
-- This is a pure version of 'System.Random.Stateful.uniformRM'.
--
-- @since 1.2
uniformR :: (RandomGen g, UniformRange a) => (a, a) -> g -> (a, g)
Expand Down
42 changes: 21 additions & 21 deletions src/System/Random/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
module System.Random.Internal
(-- * Pure and monadic pseudo-random number generator interfaces
RandomGen(..)
, MonadRandom(..)
, StatefulGen(..)

-- ** Standard pseudo-random number generator
, StdGen(..)
Expand Down Expand Up @@ -179,8 +179,8 @@ class RandomGen g where
split :: g -> (g, g)


-- | 'MonadRandom' is an interface to monadic pseudo-random number generators.
class Monad m => MonadRandom g m where
-- | 'StatefulGen' is an interface to monadic pseudo-random number generators.
class Monad m => StatefulGen g m where
-- | @uniformWord32R upperBound g@ generates a 'Word32' that is uniformly
-- distributed over the range @[0, upperBound]@.
--
Expand Down Expand Up @@ -316,7 +316,7 @@ pinnedByteArrayToForeignPtr ba# =
-- | Generates a pseudo-random 'ByteString' of the specified size.
--
-- @since 1.2
uniformByteString :: MonadRandom g m => Int -> g -> m ByteString
uniformByteString :: StatefulGen g m => Int -> g -> m ByteString
uniformByteString n g = do
ba@(SBS ba#) <- uniformShortByteString n g
pure $
Expand All @@ -332,7 +332,7 @@ uniformByteString n g = do
-- @since 1.2
data StateGenM g = StateGenM

instance (RandomGen g, MonadState g m) => MonadRandom (StateGenM g) m where
instance (RandomGen g, MonadState g m) => StatefulGen (StateGenM g) m where
uniformWord32R r _ = state (genWord32R r)
uniformWord64R r _ = state (genWord64R r)
uniformWord8 _ = state genWord8
Expand Down Expand Up @@ -422,7 +422,7 @@ class Uniform a where
-- type.
--
-- @since 1.2
uniformM :: MonadRandom g m => g -> m a
uniformM :: StatefulGen g m => g -> m a

-- | The class of types for which a uniformly distributed value can be drawn
-- from a range.
Expand All @@ -443,7 +443,7 @@ class UniformRange a where
-- > uniformRM (a, b) = uniformRM (b, a)
--
-- @since 1.2
uniformRM :: MonadRandom g m => (a, a) -> g -> m a
uniformRM :: StatefulGen g m => (a, a) -> g -> m a

instance UniformRange Integer where
uniformRM = uniformIntegralM
Expand Down Expand Up @@ -688,7 +688,7 @@ instance UniformRange Bool where
uniformRM (True, True) _g = return True
uniformRM _ g = uniformM g

-- | See /Floating point number caveats/ in "System.Random.Monad".
-- | See /Floating point number caveats/ in "System.Random.Stateful".
instance UniformRange Double where
uniformRM (l, h) g = do
w64 <- uniformWord64 g
Expand All @@ -704,7 +704,7 @@ word64ToDoubleInUnitInterval w64 = d / m
m = fromIntegral (maxBound :: Word64) :: Double
{-# INLINE word64ToDoubleInUnitInterval #-}

-- | See /Floating point number caveats/ in "System.Random.Monad".
-- | See /Floating point number caveats/ in "System.Random.Stateful".
instance UniformRange Float where
uniformRM (l, h) g = do
w32 <- uniformWord32 g
Expand Down Expand Up @@ -754,7 +754,7 @@ randomIvalInteger (l,h) rng

-- | Generate an integral in the range @[l, h]@ if @l <= h@ and @[h, l]@
-- otherwise.
uniformIntegralM :: (Bits a, Integral a, MonadRandom g m) => (a, a) -> g -> m a
uniformIntegralM :: (Bits a, Integral a, StatefulGen g m) => (a, a) -> g -> m a
uniformIntegralM (l, h) gen = case l `compare` h of
LT -> do
let limit = h - l
Expand All @@ -778,7 +778,7 @@ uniformIntegralM (l, h) gen = case l `compare` h of
-- https://doi.org/10.1145/3230636
--
-- PRECONDITION (unchecked): s > 0
boundedExclusiveIntegralM :: forall a g m . (Bits a, Integral a, MonadRandom g m) => a -> g -> m a
boundedExclusiveIntegralM :: forall a g m . (Bits a, Integral a, StatefulGen g m) => a -> g -> m a
boundedExclusiveIntegralM (s :: a) gen = go
where
n = integralWordSize s
Expand All @@ -789,7 +789,7 @@ boundedExclusiveIntegralM (s :: a) gen = go
modTwoToKMask = twoToK - 1

t = (twoToK - s) `mod` s
go :: (Bits a, Integral a, MonadRandom g m) => m a
go :: (Bits a, Integral a, StatefulGen g m) => m a
go = do
x <- uniformIntegralWords n gen
let m = x * s
Expand All @@ -813,7 +813,7 @@ integralWordSize = go 0

-- | @uniformIntegralWords n@ is a uniformly pseudo-random integral in the range
-- @[0, WORD_SIZE_IN_BITS^n)@.
uniformIntegralWords :: (Bits a, Integral a, MonadRandom g m) => Int -> g -> m a
uniformIntegralWords :: (Bits a, Integral a, StatefulGen g m) => Int -> g -> m a
uniformIntegralWords n gen = go 0 n
where
go !acc i
Expand All @@ -826,14 +826,14 @@ uniformIntegralWords n gen = go 0 n
-- | Uniformly generate an 'Integral' in an inclusive-inclusive range.
--
-- Only use for integrals size less than or equal to that of 'Word32'.
unbiasedWordMult32RM :: (MonadRandom g m, Integral a) => (a, a) -> g -> m a
unbiasedWordMult32RM :: (StatefulGen g m, Integral a) => (a, a) -> g -> m a
unbiasedWordMult32RM (b, t) g
| b <= t = (+b) . fromIntegral <$> unbiasedWordMult32 (fromIntegral (t - b)) g
| otherwise = (+t) . fromIntegral <$> unbiasedWordMult32 (fromIntegral (b - t)) g
{-# SPECIALIZE unbiasedWordMult32RM :: MonadRandom g m => (Word8, Word8) -> g -> m Word8 #-}
{-# SPECIALIZE unbiasedWordMult32RM :: StatefulGen g m => (Word8, Word8) -> g -> m Word8 #-}

-- | Uniformly generate Word32 in @[0, s]@.
unbiasedWordMult32 :: MonadRandom g m => Word32 -> g -> m Word32
unbiasedWordMult32 :: StatefulGen g m => Word32 -> g -> m Word32
unbiasedWordMult32 s g
| s == maxBound = uniformWord32 g
| otherwise = unbiasedWordMult32Exclusive (s+1) g
Expand All @@ -845,12 +845,12 @@ unbiasedWordMult32 s g
-- more directly [O\'Neill's github
-- repo](https://github.com/imneme/bounded-rands/blob/3d71f53c975b1e5b29f2f3b05a74e26dab9c3d84/bounded32.cpp#L234).
-- N.B. The range is [0,t) **not** [0,t].
unbiasedWordMult32Exclusive :: forall g m . MonadRandom g m => Word32 -> g -> m Word32
unbiasedWordMult32Exclusive :: forall g m . StatefulGen g m => Word32 -> g -> m Word32
unbiasedWordMult32Exclusive r g = go
where
t :: Word32
t = (-r) `mod` r -- Calculates 2^32 `mod` r!!!
go :: MonadRandom g m => m Word32
go :: StatefulGen g m => m Word32
go = do
x <- uniformWord32 g
let m :: Word64
Expand All @@ -862,7 +862,7 @@ unbiasedWordMult32Exclusive r g = go

-- | This only works for unsigned integrals
unsignedBitmaskWithRejectionRM ::
(MonadRandom g m, FiniteBits a, Num a, Ord a, Uniform a)
(StatefulGen g m, FiniteBits a, Num a, Ord a, Uniform a)
=> (a, a)
-> g
-> m a
Expand All @@ -875,7 +875,7 @@ unsignedBitmaskWithRejectionRM (bottom, top) gen

-- | This works for signed integrals by explicit conversion to unsigned and abusing overflow
signedBitmaskWithRejectionRM ::
(Num a, Num b, Ord b, Ord a, FiniteBits a, MonadRandom g f, Uniform a)
(Num a, Num b, Ord b, Ord a, FiniteBits a, StatefulGen g f, Uniform a)
=> (b -> a)
-> (a -> b)
-> (b, b)
Expand All @@ -894,7 +894,7 @@ signedBitmaskWithRejectionRM toUnsigned fromUnsigned (bottom, top) gen
{-# INLINE signedBitmaskWithRejectionRM #-}

unsignedBitmaskWithRejectionM ::
forall a g m . (Ord a, FiniteBits a, Num a, MonadRandom g m) => (g -> m a) -> a -> g -> m a
forall a g m . (Ord a, FiniteBits a, Num a, StatefulGen g m) => (g -> m a) -> a -> g -> m a
unsignedBitmaskWithRejectionM genUniformM range gen = go
where
mask :: a
Expand Down
Loading

0 comments on commit 78e0f84

Please sign in to comment.