在以下示例中:
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
我很困惑:
为什么foo的签名被强制为StateT Int RVar ()
,即使toss'
对某些m Bool
具有签名MonadRandom m
为什么testFoo
必须与某些StdRandom
一起运行,即使toss'
已runRVar
StdRandom
。从类型的角度来看,它是有意义的,但StdRandom
最终被使用了哪些?如果这个问题有意义的话。
是否可以将foo
的签名重写为MonadRandom m => StateT Int m ()
答案 0 :(得分:4)
RVar
中一样将bar
添加到monad堆栈。 MonadRandom
过于笼统。
StdRandom
只是一个数据构造函数,因此它没有特定的状态。 random-fu
应自动处理更新状态。