Skip to content

Commit

Permalink
Merge pull request #121 from idontgetoutmuch/uniform-uniformr-docs
Browse files Browse the repository at this point in the history
Improve 'uniform' and 'uniformR' docs
  • Loading branch information
lehins authored May 7, 2020
2 parents a091bfc + 07016de commit 5e78a97
Showing 4 changed files with 82 additions and 38 deletions.
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -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
54 changes: 51 additions & 3 deletions System/Random.hs
Original file line number Diff line number Diff line change
@@ -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
-- <https://hackage.haskell.org/package/splitmix splitmix> 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:
-- <https://doi.org/10.1145/2660193.2660195>

-- $setup
--
-- >>> import Control.Monad (replicateM)
-- >>> import Data.List (unfoldr)
8 changes: 4 additions & 4 deletions System/Random/Internal.hs
Original file line number Diff line number Diff line change
@@ -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:
--
50 changes: 21 additions & 29 deletions System/Random/Monad.hs
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 5e78a97

Please sign in to comment.