Question: I want to use do notation to combine pseudo-random values:

```
g :: StdGen
g = mkStdGen 100

example1 :: Bool
example1
  = fst
  $ runState
    (do x <- state (uniformR (False,True))
        y <- state (uniformR (False,True))
        return $ x == y
    )
    g

```

Function `uniformR` is defined in terms of the System.Random.Stateful module:

```
uniformR :: (RandomGen g, UniformRange a) => (a, a) -> g -> (a, g)
uniformR r g = runStateGen g (uniformRM r)

```

so in my example, it seems silly for `uniformR` to create and run state, only for my example to create and run state again.

Is there a way to rewrite example 1, using System.Random.Stateful and do notation?

This is the only thing I could get to work (which is ridiculous):

```
example3 :: Bool
example3
  = fst
  $ runStateGen
    g
    (do x <- uniformRM (False,True)
        y <- uniformRM (False,True)
        return $ do x' <- x
                    y' <- y
                    return $ x'==y')

```

It seems like what I need is some type of monad transformer?

Answer: 
It is much simpler than one would imagine:

```hs
example4 :: Bool
example4 = runStateGen_ (mkStdGen 100) $ \gen -> do
  x <- uniformRM (False,True) gen
  y <- uniformRM (False,True) gen
  pure (x == y)

```

Of course `uniformRM (False, True) == unformM`, but that is probably irrelevant, since that was just an example to demonstrate the question, I imagine.

More info can be found in haddock as well as in [this blogpost](https://alexey.kuleshevi.ch/blog/2021/01/29/random-interface/) and [this video presentation](https://www.youtube.com/watch?v=GGbPqSM1ADw)
The second argument to `runStateGen` is `StateGenM g -> State g a`, which is `ReaderT` in disguise:

```
import Control.Monad.Reader (ReaderT(..), runReaderT)
import Control.Applicative (liftA2)
import qualified System.Random.Stateful as Random

uniformRM :: (Random.UniformRange a, Random.StatefulGen g m) => (a, a) -> ReaderT g m a
uniformRM r = ReaderT (Random.uniformRM r)

g :: Random.StdGen
g = Random.mkStdGen 100

example1
  = Random.runStateGen_ g
  $ runReaderT
  $ liftA2 (==) (uniformRM (False,True)) (uniformRM (False,True))

```