我看到这里
-- 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.
Run Code Online (Sandbox Code Playgroud)
说实话,我不太明白这个注释。他们是否意味着可以打破forever
,MonadPlus
例如 - IO Bool
?就说吧,IO False
会打破它...
从某一方面来说IO
也是MonadPlus
如此。也许我必须用其他东西包裹我才能实现与andIO Bool
决裂的可能性?这条注释到底是什么意思?forever
IO Bool
MonadPlus
当然,我可以例外地打破它或实现自己的,forever
但我的兴趣在于这个奇怪的注释。
Gia*_*eri 12
你可以看看是如何forever
实现的:
forever :: Applicative f => f a -> f b -> f b
forever a = let a' = a *> a' in a'
Run Code Online (Sandbox Code Playgroud)
的文档(*>)
说它“对操作进行排序,丢弃第一个参数的值”。它基本上是(>>)
Applicatives 而不是 Monads。
因此,如果您查看forever
其实现方式,您会发现它基本上扩展为:
forever a = a *> a *> a *> ...
Run Code Online (Sandbox Code Playgroud)
正如forever
描述所述,如果应用程序有一些短路行为,它仍然可以终止并且不评估无限的操作序列:
ghci> forever $ Nothing
Nothing
ghci> forever $ Just 1
-- infinite loop trying to evaluate Just 1 *> Just 1 *> Just 1 *> ...
Run Code Online (Sandbox Code Playgroud)
这是因为(Nothing *> _) = Nothing
后面的内容(*>)
甚至都没有被评估,因此无需评估无限的操作列表Nothing *> Nothing *> Nothing *> ...
即可短路。Nothing
Li-*_*Xia 11
人们可能天真地认为这种情况forever m
会永远持续下去:
forever m = m >> forever m
= m >> m >> forever m
= m >> m >> m >> ... -- forever
Run Code Online (Sandbox Code Playgroud)
但评论提到有一些方法可以打破循环,并且mzero
是一个简洁的示例,它以等式方式演示了情况,而不是通过操作性地考虑异常。mzero
满足mzero >> w = mzero
所有人w
,因此:
forever mzero = mzero >> forever mzero
= mzero
Run Code Online (Sandbox Code Playgroud)
关键是,单子的选择forever
比命令式语言中的单纯循环更加通用while (true)
。