```{- |
Monadic functions for random number generation.

Because manually threading the correct 'Seed' value around is
tedious and error-prone, one common approach is to use some
kind of state monad to hide it. This module provides the
convenience functions to make this easy; just write a
can easily and conveniently generate random numbers.
-}

(
-- * Random seed
Seed (),

RandomM (..),

bounded_randomM, unit_randomM, range_randomM,
)
where

import Random.MWC.Pure

{- |
The class of monads holding a single random 'Seed' within their
state.
-}
class Monad m => RandomM m where
-- | Fetch the current 'Seed' value.
get_random_seed :: m Seed

-- | Replace the current 'Seed' value.
set_random_seed :: Seed -> m ()

{- |

Return a value randomly chosen between 'minBound' and 'maxBound'.
Uses the current 'Seed' value from within the monad, automatically
updating said seed value in the process. Thus, repeatedly calling
this function will yield different successive values.
-}
bounded_randomM :: (RandomM m, BoundedRandom x) => m x
bounded_randomM = do
s0 <- get_random_seed
let (x, s1) = bounded_random s0
set_random_seed s1
return x

{- |

Returns a value randomly chosen between \"zero\" and \"one\". Uses
the current 'Seed' value from within the monad, automatically
updating said seed value in the process. Thus, repeatedly calling
this function will yield different successive values.
-}
unit_randomM :: (RandomM m, UnitRandom x) => m x
unit_randomM = do
s0 <- get_random_seed
let (x, s1) = unit_random s0
set_random_seed s1
return x

{- |

Returns a value randomly chosen from a user-specified range
(inclusive). Uses the current 'Seed' value from within the monad,
automatically updating said seed value in the process. Thus,
repeatedly calling this function will yield different successive
values.
-}
range_randomM :: (RandomM m, RangeRandom x) => (x, x) -> m x
range_randomM xr = do
s0 <- get_random_seed
let (x, s1) = range_random xr s0
set_random_seed s1
return x
```