##### Views

equivalent of
RandomGen
's
split
function:
```class (MonadRandom m) => MonadRandomSplittable m where
splitRandom :: m a -> m a

splitRandom ma  = (RandomT . liftState) split >>= lift . evalRandomT ma```

MonadRandomSplittable can then be derived for Rand by GHC:

```newtype Rand g a = Rand { unRand :: RandomT g Identity a }

Some potentially useful functions

```splitRandoms        :: MonadRandomSplittable m => [m a] -> m [a]
splitRandoms []     = splitRandom \$ return []
splitRandoms (x:xs) = splitRandom \$ liftM2 (:) x (splitRandoms xs)

getRandoms      :: (MonadRandomSplittable m, Random a) => m [a]
getRandoms      = liftM2 (:) getRandom (splitRandom getRandoms)

getRandomRs     :: (MonadRandomSplittable m, Random a) => (a, a) -> m [a]
getRandomRs b   = liftM2 (:) (getRandomR b) (splitRandom (getRandomRs b))```

## 1 Example of usage

```test   :: Rand StdGen [Bool] -> (Int, [Bool], Int)
test ma = evalRand (liftM3 (,,) (getRandomR (0,99)) ma (getRandomR (0,99)))
(mkStdGen 0)```

Then

```*MonadRandom> test (replicateM 0 getRandom)
(45,[],55)
(45,[True,True],0)

*MonadRandom> test (splitRandom \$ replicateM 0 getRandom)
(45,[],16)
*MonadRandom> test (splitRandom \$ replicateM 2 getRandom)
(45,[False,True],16)

*MonadRandom> case test undefined of (a,_,c) -> (a,c)
*** Exception: Prelude.undefined
*MonadRandom> case test (splitRandom undefined) of (a,_,c) -> (a,c)
(45,16)```

## 2 Laws

It is not clear to me exactly what laws
splitRandom
should satisfy, besides monadic variations of the "split laws" from the Haskell Library Report For all terminating
ma
and
mb
, it should hold that
`  liftM3 (\a _ c -> (a,c)) getRandom ma getRandom === liftM3 (\a _ c -> (a,c)) getRandom mb getRandom`

For monad transformers, it would also be nice if

`splitRandom undefined === splitRandom (return ()) >> lift undefined`

For example,

```>runIdentity \$ runRandomT (splitRandom (return ()) >> lift undefined >> return ()) (mkStdGen 0)
((),40014 2147483398)
>runIdentity \$ runRandomT (splitRandom undefined >> return ()) (mkStdGen 0)
((),40014 2147483398)```

But

```>runRandomT (splitRandom (return ()) >> lift undefined >> return ()) (mkStdGen 0)
*** Exception: Prelude.undefined
>runRandomT (splitRandom undefined >> return ()) (mkStdGen 0)
*** Exception: Prelude.undefined```
I have no idea how to express this idea for monads that aren't transformers though. But for
Rand
it means that:
```>runRand (splitRandom undefined >> return ()) (mkStdGen 0)
((),40014 2147483398)```

## 3 Why?

In
replicateM 100 (splitRandom expensiveAction)
There are no RNG-dependencies between the different expensiveActions, so they may be computed in parallel.
```data Tree a = Branch a (Tree a) (Tree a) | Leaf deriving (Eq, Show)

makeRandomTree  = do
this  <- getRandomR (0,9)
left  <- splitRandom makeRandomTree
right <- splitRandom makeRandomTree
return \$ Branch this left right```

By removing the RNG-dependencies, infinite random data structures can be constructed lazily.

And for completeness the non-monadic version:

```randomTree g    = Branch a (randomTree gl) (randomTree gr)
where
(a, g') = randomR (0, 9) g
(gl, gr)= split g'```

Note that the monadic version needs one split operation more, so yields different results.