[Haskell-cafe] random-fu confusion

James Andrew Cook mokus at deepbondi.net
Tue Sep 7 13:04:28 EDT 2010

On Sep 7, 2010, at 10:21 AM, Alex Rozenshteyn wrote:

> Okay, I figured the immutability bit out and I got the IORef example working, but I can't get it to work with state.
> > put (pureMT 0) >>= runRVar flipCoin
> gives me two type errors: "No instance for (MonadState PureMT m)" and "No instance for (RandomSource m ())"

The first error is because "put" has the general type: "put :: (MonadState s m) => s -> m ()" and GHC doesn't know what monad you want to evaluate it in.  Just off the bat there are 2 possibilities provided by Control.Monad.State: State and StateT.
The second is because runRVar requires an additional argument specifying the source from which to sample.  In your case, you want to sample from the "standard" source, the MonadRandom instance.  The type "StdRandom" with a single constructor of the same name designates the MonadRandom instance.  So for your example, a working incantation would be:

> put (pureMT 0) >>= runRVar flipCoin StdRandom :: State PureMT Bool

To actually run this action you would then use runState or evalState, in which case the type annotation would no longer be necessary because the use of runState or evalState would give the compiler enough information to know what you want.  These functions both also accept an initial state as an argument, so you don't actually need "put" either:

> evalState (runRVar flipCoin StdRandom) (pureMT 0)

Using the "sample" function I mentioned earlier you can leave off the mention of StdRandom:

> evalState (sample flipCoin) (pureMT 0)

>  I'm trying to do figure out how to do this without going to the IO monad (so I can run it with the same seed to replicate results).

Incidentally, you can use the 'pureMT' function to seed your generator in the IO monad just as easily:

> newIORef (pureMT 0) >>= \src -> runRVar flipCoin src

> do src <- newIORef (pureMT 0); runRVar flipCoin src

A large part of the point of the RVar monad as its own independent construct is to allow you to use random variables such as flipCoin in any monad that can support them while at the same time guaranteeing all the same purity / safety as if you had used something "obviously" pure such as State.

-- James

More information about the Haskell-Cafe mailing list