diff --git a/.gitignore b/.gitignore index 41c6d8c61..488b83d15 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,10 @@ GNUmakefile dist-install/ ghc.mk -dist -.cabal-sandbox +.cabal-sandbox/ +.stack-work/ +cabal.project.local cabal.sandbox.config +dist-newstyle/ +dist/ +stack.yaml.lock diff --git a/System/Random.hs b/System/Random.hs index 3741ce0d3..9256f5575 100644 --- a/System/Random.hs +++ b/System/Random.hs @@ -14,6 +14,9 @@ module System.Random -- * Introduction -- $introduction + -- * Usage + -- $usagepure + -- * Pure number generator interface -- $interfaces RandomGen(..) @@ -76,6 +79,31 @@ import qualified System.Random.SplitMix as SM -- package. -- Programmers may, of course, supply their own instances of 'RandomGen'. -- +-- $usagepure +-- +-- In pure code, use 'uniform' and 'uniformR' to generate pseudo-random values +-- with a pure pseudo-random number generator like 'StdGen'. +-- +-- >>> :{ +-- let rolls :: RandomGen g => Int -> g -> [Word8] +-- rolls n = take n . unfoldr (Just . uniformR (1, 6)) +-- pureGen = mkStdGen 137 +-- in +-- rolls 10 pureGen :: [Word8] +-- :} +-- [1,2,6,6,5,1,4,6,5,4] +-- +-- To run use a /monadic/ pseudo-random computation in pure code with a pure +-- pseudo-random number generator, use 'runGenState' and its variants. +-- +-- >>> :{ +-- let rollsM :: MonadRandom g s m => Int -> g s -> m [Word8] +-- rollsM n = replicateM n . uniformRM (1, 6) +-- pureGen = mkStdGen 137 +-- in +-- runGenState_ pureGen (rollsM 10) :: [Word8] +-- :} +-- [1,2,6,6,5,1,4,6,5,4] ------------------------------------------------------------------------------- -- Pseudo-random number generator interfaces @@ -99,14 +127,29 @@ import qualified System.Random.SplitMix as SM -- See "System.Random.Monad" module -- --- | Pure version of `uniformM` that works with instances of `RandomGen` +-- | Generates a value uniformly distributed over all possible values of that +-- type. +-- +-- This is a pure version of 'System.Random.Monad.uniformM'. -- -- @since 1.2 uniform :: (RandomGen g, Uniform a) => g -> (a, g) uniform g = runGenState g uniformM - --- | Pure version of `uniformRM` that works with instances of `RandomGen` +-- | Generates a value uniformly distributed over the provided range, which +-- is interpreted as inclusive in the lower and upper bound. +-- +-- * @uniformR (1 :: Int, 4 :: Int)@ generates values uniformly from the set +-- \(\{1,2,3,4\}\) +-- +-- * @uniformR (1 :: Float, 4 :: Float)@ generates values uniformly from the +-- set \(\{x\;|\;1 \le x \le 4\}\) +-- +-- The following law should hold to make the function always defined: +-- +-- > uniformR (a, b) = uniformR (b, a) +-- +-- This is a pure version of 'System.Random.Monad.uniformRM'. -- -- @since 1.2 uniformR :: (RandomGen g, UniformRange a) => (a, a) -> g -> (a, g) @@ -417,3 +460,8 @@ randomIO = liftIO $ getStdRandom random -- International Conference on Object Oriented Programming Systems Languages & -- Applications (OOPSLA '14). ACM, New York, NY, USA, 453-472. DOI: -- + +-- $setup +-- +-- >>> import Control.Monad (replicateM) +-- >>> import Data.List (unfoldr) diff --git a/System/Random/Internal.hs b/System/Random/Internal.hs index 76e101660..f88b08f6d 100644 --- a/System/Random/Internal.hs +++ b/System/Random/Internal.hs @@ -439,11 +439,11 @@ class UniformRange a where -- | Generates a value uniformly distributed over the provided range, which -- is interpreted as inclusive in the lower and upper bound. -- - -- * @uniformR (1 :: Int, 4 :: Int)@ should generate values uniformly from - -- the set \(\{1,2,3,4\}\) + -- * @uniformRM (1 :: Int, 4 :: Int)@ generates values uniformly from the + -- set \(\{1,2,3,4\}\) -- - -- * @uniformR (1 :: Float, 4 :: Float)@ should generate values uniformly - -- from the set \(\{x\;|\;1 \le x \le 4\}\) + -- * @uniformRM (1 :: Float, 4 :: Float)@ generates values uniformly from + -- the set \(\{x\;|\;1 \le x \le 4\}\) -- -- The following law should hold to make the function always defined: -- diff --git a/System/Random/Monad.hs b/System/Random/Monad.hs index 309e8bfad..3c98b7db0 100644 --- a/System/Random/Monad.hs +++ b/System/Random/Monad.hs @@ -109,43 +109,35 @@ import System.Random.Internal -- -- $usagemonadic -- --- == How to generate pseudo-random values in monadic code --- -- In monadic code, use the relevant 'Uniform' and 'UniformRange' instances to -- generate pseudo-random values via 'uniformM' and 'uniformRM', respectively. -- --- As an example, @rolls@ generates @n@ pseudo-random values of @Word8@ in the --- range @[1, 6]@. +-- 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 +-- number generator, you can run this probabilistic computation as follows: -- -- >>> :{ --- let rolls :: MonadRandom g s m => Int -> g s -> m [Word8] --- rolls n = replicateM n . uniformRM (1, 6) +-- let rollsM :: MonadRandom g s m => Int -> g s -> m [Word8] +-- rollsM n = replicateM n . uniformRM (1, 6) +-- in do +-- monadicGen <- MWC.create +-- rollsM 10 monadicGen :: IO [Word8] -- :} +-- [4,1,2,4,4,5,2,1,5,4] -- --- Given a /monadic/ pseudo-random number generator, you can run this --- probabilistic computation as follows: --- --- >>> monadicGen <- MWC.create --- >>> rolls 12 monadicGen :: IO [Word8] --- [4,1,2,4,4,5,2,1,5,4,6,6] --- --- Given a /pure/ pseudo-random number generator, you can run it in an 'IO' or --- 'ST' context by first applying a monadic adapter like 'AtomicGen', 'IOGen' --- or 'STGen' and then running it with 'runGenM'. --- --- >>> let pureGen = mkStdGen 41 --- >>> runGenM_ (IOGen pureGen) (rolls 10) :: IO [Word8] --- [6,4,5,1,1,3,2,4,5,5] +-- Given a /pure/ pseudo-random number generator, you can run the monadic +-- pseudo-random number computation @rollsM@ in an 'IO' or 'ST' context by +-- first applying a monadic adapter like 'AtomicGen', 'IOGen' or 'STGen' to the +-- pure pseudo-random number generator and then running it with 'runGenM'. -- --- == How to generate pseudo-random values in pure code --- --- In pure code, use 'runGenState' and its variants to extract the pure --- pseudo-random value from a monadic computation based on a pure pseudo-random --- number generator. --- --- >>> let pureGen = mkStdGen 41 --- >>> runGenState_ pureGen (rolls 10) :: [Word8] --- [6,4,5,1,1,3,2,4,5,5] +-- >>> :{ +-- let rollsM :: MonadRandom g s m => Int -> g s -> m [Word8] +-- rollsM n = replicateM n . uniformRM (1, 6) +-- pureGen = mkStdGen 42 +-- in +-- runGenM_ (IOGen pureGen) (rollsM 10) :: IO [Word8] +-- :} +-- [5,1,4,3,3,2,5,2,2,4] ------------------------------------------------------------------------------- -- Pseudo-random number generator interfaces