MonadPlus 和forever - 有什么关系?

问题描述 投票:0回答:2

我看到这里

-- Note that "forever" isn't necessarily non-terminating.
-- If the action is in a @'MonadPlus'@ and short-circuits after some number of iterations.
-- then @'forever'@ actually returns `mzero`, effectively short-circuiting its caller.

说实话我不明白这个注释。他们是否意味着可以用

forever
来打破
MonadPlus
,例如 -
IO Bool
?假设,
IO False
会破坏它...

从某一角度来看,

IO
也是
MonadPlus
。也许我必须用其他东西包裹我的
IO Bool
才能实现用
forever
IO Bool
打破
MonadPlus
的可能性?注释到底是什么意思?

当然,我可以例外地打破它或实现自己的

forever
,但我的兴趣在于这个奇怪的注释。

haskell monads monadplus
2个回答
13
投票

你可以看看

forever
是如何实现的:

forever :: Applicative f => f a -> f b -> f b
forever a = let a' = a *> a' in a'

(*>)
的文档说它“序列操作,丢弃第一个参数的值”。它基本上是 Applicatives 而不是 Monad 的
(>>)

因此,如果您查看

forever
的实现方式,您会发现它基本上扩展为:

forever a = a *> a *> a *> ...

正如

forever
描述所述,如果 Applicative 有一些短路行为,它仍然可以终止并且不评估无限的操作序列:

ghci> forever $ Nothing
Nothing
ghci> forever $ Just 1
-- infinite loop trying to evaluate Just 1 *> Just 1 *> Just 1 *> ...

这是因为

(Nothing *> _) = Nothing
之后的
(*>)
甚至都没有被评估,所以
Nothing *> Nothing *> Nothing *> ...
短路到
Nothing
而无需评估无限的操作列表。


11
投票

人们可能天真地认为

forever m
会永远持续下去:

forever m = m >> forever m
          = m >> m >> forever m
          = m >> m >> m >> ...  -- forever

但是评论提到有一些方法可以打破循环,并且

mzero
是一个简洁的示例,它以等式方式演示了情况,而不是通过操作性地考虑异常。
mzero
满足所有
mzero >> w = mzero
w
,因此:

forever mzero = mzero >> forever mzero
              = mzero

重点是,monad 的选择使得

forever
比命令式语言中单纯的
while (true)
循环更加通用。

© www.soinside.com 2019 - 2024. All rights reserved.