diff --git a/bench/Main.hs b/bench/Main.hs index 38904c5c7..caa116dc3 100644 --- a/bench/Main.hs +++ b/bench/Main.hs @@ -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 diff --git a/random.cabal b/random.cabal index 6d6f69e9e..c61d657ba 100644 --- a/random.cabal +++ b/random.cabal @@ -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 @@ -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 @@ -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 diff --git a/src/System/Random.hs b/src/System/Random.hs index dab90f20f..c5604817f 100644 --- a/src/System/Random.hs +++ b/src/System/Random.hs @@ -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 @@ -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) @@ -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) diff --git a/src/System/Random/Internal.hs b/src/System/Random/Internal.hs index 8be88332c..faeb53dbf 100644 --- a/src/System/Random/Internal.hs +++ b/src/System/Random/Internal.hs @@ -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(..) @@ -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]@. -- @@ -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 $ @@ -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 @@ -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. @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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) @@ -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 diff --git a/src/System/Random/Monad.hs b/src/System/Random/Stateful.hs similarity index 94% rename from src/System/Random/Monad.hs rename to src/System/Random/Stateful.hs index c0e1dffd4..63045c14e 100644 --- a/src/System/Random/Monad.hs +++ b/src/System/Random/Stateful.hs @@ -9,14 +9,14 @@ {-# LANGUAGE UndecidableInstances #-} -- | --- Module : System.Random.Monad +-- 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.Monad +module System.Random.Stateful ( -- * Pure Random Generator module System.Random @@ -28,7 +28,7 @@ module System.Random.Monad -- * Pure and monadic pseudo-random number generator interfaces -- $interfaces - , MonadRandom(..) + , StatefulGen(..) , RandomGenM(..) , randomM , randomRM @@ -72,7 +72,7 @@ module System.Random.Monad -- * Appendix - -- ** How to implement 'MonadRandom' + -- ** How to implement 'StatefulGen' -- $implementmonadrandom -- ** Floating point number caveats @@ -94,11 +94,11 @@ import System.Random.Internal -- -- This module provides type classes and instances for the following concepts: -- --- [Monadic pseudo-random number generators] 'MonadRandom' is an interface to +-- [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 'MonadRandom' instance. +-- 'RandomGen' instance into a 'StatefulGen' instance. -- -- [Drawing from a range] 'UniformRange' is used to generate a value of a -- type uniformly within a range. @@ -118,11 +118,11 @@ import System.Random.Internal -- generate pseudo-random values via 'uniformM' and 'uniformRM', respectively. -- -- As an example, @rollsM@ generates @n@ pseudo-random values of @Word8@ in the --- range @[1, 6]@ in a 'MonadRandom' context; given a /monadic/ pseudo-random +-- range @[1, 6]@ in a 'StatefulGen' context; given a /monadic/ pseudo-random -- number generator, you can run this probabilistic computation as follows: -- -- >>> :{ --- 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) -- in do -- monadicGen <- MWC.create @@ -135,7 +135,7 @@ import System.Random.Internal -- using a monadic adapter like 'AtomicGenM', 'IOGenM' or 'STGenM'. -- -- >>> :{ --- 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 42 -- in @@ -154,7 +154,7 @@ import System.Random.Internal -- ['System.Random.RandomGen': pure pseudo-random number generators] -- See "System.Random" module. -- --- ['MonadRandom': monadic pseudo-random number generators] These generators +-- ['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@. @@ -186,7 +186,7 @@ import System.Random.Internal -- | Interface to operations on 'RandomGen' wrappers like 'IOGenM' and 'StateGenM'. -- -- @since 1.2 -class (RandomGen r, MonadRandom g m) => RandomGenM g r m | g -> r where +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 @@ -211,7 +211,7 @@ instance RandomGen r => RandomGenM (STGenM r s) r (ST s) where -- | Generates a list of pseudo-random values. -- -- @since 1.2 -uniformListM :: (MonadRandom g m, Uniform a) => g -> Int -> m [a] +uniformListM :: (StatefulGen g m, Uniform a) => g -> Int -> m [a] uniformListM gen n = replicateM n (uniformM gen) -- | Generates a pseudo-random value using monadic interface and `Random` instance. @@ -239,7 +239,7 @@ newtype AtomicGenM g = AtomicGenM { unAtomicGenM :: IORef g} newAtomicGenM :: MonadIO m => g -> m (AtomicGenM g) newAtomicGenM = fmap AtomicGenM . liftIO . newIORef -instance (RandomGen g, MonadIO m) => MonadRandom (AtomicGenM g) m where +instance (RandomGen g, MonadIO m) => StatefulGen (AtomicGenM g) m where uniformWord32R r = applyAtomicGen (genWord32R r) {-# INLINE uniformWord32R #-} uniformWord64R r = applyAtomicGen (genWord64R r) @@ -288,7 +288,7 @@ newtype IOGenM g = IOGenM { unIOGenM :: IORef g } newIOGenM :: MonadIO m => g -> m (IOGenM g) newIOGenM = fmap IOGenM . liftIO . newIORef -instance (RandomGen g, MonadIO m) => MonadRandom (IOGenM g) m where +instance (RandomGen g, MonadIO m) => StatefulGen (IOGenM g) m where uniformWord32R r = applyIOGen (genWord32R r) {-# INLINE uniformWord32R #-} uniformWord64R r = applyIOGen (genWord64R r) @@ -325,7 +325,7 @@ newSTGenM :: g -> ST s (STGenM g s) newSTGenM = fmap STGenM . newSTRef -instance RandomGen g => MonadRandom (STGenM g s) (ST s) where +instance RandomGen g => StatefulGen (STGenM g s) (ST s) where uniformWord32R r = applySTGen (genWord32R r) {-# INLINE uniformWord32R #-} uniformWord64R r = applySTGen (genWord64R r) @@ -479,7 +479,7 @@ runSTGen_ g action = fst $ runSTGen g action -- Here is an example instance for the monadic pseudo-random number generator -- from the @mwc-random@ package: -- --- > instance (s ~ PrimState m, PrimMonad m) => MonadRandom (MWC.Gen s) m where +-- > instance (s ~ PrimState m, PrimMonad m) => StatefulGen (MWC.Gen s) m where -- > uniformWord8 = MWC.uniform -- > uniformWord16 = MWC.uniform -- > uniformWord32 = MWC.uniform @@ -502,7 +502,7 @@ runSTGen_ g action = fst $ runSTGen g action -- >>> import Data.Int (Int32) -- >>> import Data.Word (Word8, Word16, Word32, Word64) -- >>> import System.IO (IOMode(WriteMode), withBinaryFile) --- >>> import System.Random.Monad +-- >>> import System.Random.Stateful -- >>> import qualified System.Random.MWC as MWC -- -- >>> :set -XFlexibleContexts @@ -512,7 +512,7 @@ runSTGen_ g action = fst $ runSTGen g action -- >>> :set -XUndecidableInstances -- -- >>> :{ --- instance (s ~ PrimState m, PrimMonad m) => MonadRandom (MWC.Gen s) m where +-- instance (s ~ PrimState m, PrimMonad m) => StatefulGen (MWC.Gen s) m where -- uniformWord8 = MWC.uniform -- uniformWord16 = MWC.uniform -- uniformWord32 = MWC.uniform diff --git a/test/Spec/Range.hs b/test/Spec/Range.hs index ef0d346ff..3483a9f1d 100644 --- a/test/Spec/Range.hs +++ b/test/Spec/Range.hs @@ -6,7 +6,7 @@ module Spec.Range , uniformRangeWithinExcluded ) where -import System.Random.Monad +import System.Random.Stateful symmetric :: (RandomGen g, UniformRange a, Eq a) => g -> (a, a) -> Bool symmetric g (l, r) = fst (uniformR (l, r) g) == fst (uniformR (r, l) g) diff --git a/test/Spec/Run.hs b/test/Spec/Run.hs index 6faf44e9a..6d26d5301 100644 --- a/test/Spec/Run.hs +++ b/test/Spec/Run.hs @@ -1,7 +1,7 @@ module Spec.Run (runsEqual) where import Data.Word (Word64) -import System.Random.Monad +import System.Random.Stateful runsEqual :: RandomGen g => g -> IO Bool runsEqual g = do