xiaolingxiao
xiaolingxiao

Reputation: 4895

Usage of runRVar over some monad transformer stack

In the following example:

toss :: Double -> RVar Bool
toss p = do
  q <- uniform 0 1
  return $ q <= p

toss' :: MonadRandom m => Double -> m Bool
toss' p = runRVar (toss p) StdRandom


foo :: StateT Int RVar ()
foo = do
    h <- lift $ toss' 0.5
    if h then put 100 else put 0

bar :: StateT Int RVar ()
bar = do
    h <- lift $ toss 0.5
    if h then put 404 else put 200


testFoo :: MonadRandom m => m ((), Int)
testFoo = runRVar (runStateT foo 0) StdRandom

testBar :: MonadRandom m => m ((), Int)
testBar = runRVar (runStateT bar 0) StdRandom

I am confused about:

  1. why the signature of foo is forced to be StateT Int RVar () even though toss' has signature m Bool for some MonadRandom m

  2. Why testFoo has to be run with some StdRandom even though toss' already runRVar with StdRandom. It makes sense from a type perspective, but which StdRandom end up being used? If this question makes any sense at all.

  3. Would it be possible to rewrite foo's signature as MonadRandom m => StateT Int m ()

Upvotes: 0

Views: 113

Answers (1)

David Kraeutmann
David Kraeutmann

Reputation: 118

  1. When monomorphism restriction is on (it's on by default), all types of top-level binders will be inferred monomorphic.
  2. You should add RVar to the monad stack like you did in bar. MonadRandom is too general. StdRandom is just a data constructor, so it has no specific state. random-fu should handle updating state automatically.
  3. Just add the signature. See 1.

Upvotes: 4

Related Questions