【发布时间】:2015-12-07 04:34:30
【问题描述】:
在以下示例中:
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'对某些MonadRandom m有签名m Bool为什么
testFoo必须与一些StdRandom一起运行,即使toss'已经runRVar和StdRandom。从类型的角度来看这是有道理的,但最终使用了哪个StdRandom?如果这个问题有任何意义。是否可以将
foo的签名重写为MonadRandom m => StateT Int m ()
【问题讨论】:
-
runRVar的类型非常一般 - 在这种情况下,当您在foo和 @987654339 内部使用toss'时,第一个runRVar将被实例化为RVar Bool -> StdRandom -> RVar Bool类型@。而这个功能只是身份(或应该是)。在任何情况下,StdRandom 都不会“做”任何事情 - 当您编写runRVar ... StdRandom时,它只是意味着使用MonadRandom接口作为随机源。
标签: haskell monads monad-transformers