在一些 monad 转换器堆栈上使用 runRVar
Usage of runRVar over some monad transformer stack
在下面的例子中:
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 ()
- 当单态限制开启时(默认开启),所有类型的顶级绑定器都将被推断为单态。
- 您应该像在
bar
中那样将 RVar
添加到 monad 堆栈。 MonadRandom
太笼统了。
StdRandom
只是一个数据构造函数,所以没有具体的状态。 random-fu
应自动处理更新状态。
- 只需添加签名。见 1.
在下面的例子中:
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 ()
- 当单态限制开启时(默认开启),所有类型的顶级绑定器都将被推断为单态。
- 您应该像在
bar
中那样将RVar
添加到 monad 堆栈。MonadRandom
太笼统了。StdRandom
只是一个数据构造函数,所以没有具体的状态。random-fu
应自动处理更新状态。 - 只需添加签名。见 1.