For quite a while, a package called MonadRandom by Cale Gibbard has been available on Hackage. At first it seems like just a little silly convenience module. But I argue that it should be used instead of System.Random whenever possible, not just when it’s more convenient. Here’s why:

What’s a RandomGen?

class RandomGen g where next :: g -> (Int, g) split :: g -> (g,g) genRange :: g -> (Int,Int)

It’s this thing… this thingamajigger, if you prefer, which has a next, a split, and a genRange. Cool, that’s great. Um… so, what are those things? What do they mean? And what do they have to do with randomness? next. NEXT? That doesn’t seem very random!

MonadRandom is very humble in its self-description:

Computation type: Computations which consume random values. Binding strategy: The computation proceeds in the same fashion as the identity monad, but it carries a random number generator that may be queried to generate random values.

But it means much more than it says. Rand a is not merely an “identity monad carrying a random number generator” (a random number generator being one of those what-the-heck-is-thats above). Rand a is a probability distribution of a’s! Which is simple, meaningful and easy to reason about!

We can model it like so:

Rand a = a -> Real fmap f p x = ∑ p[f-1[{x}]] return x = δ(x) (p >>= f) x = ∑ y p(y) f(y)(x)

With getRandom etc. being standard distributions on various data types.

As long as your computations are in Rand (I don’t give a hoot about RandT), you can use this semantics for precise, mathematical reasoning. What did you have when you were using RandomGen?