【发布时间】:2017-06-21 13:57:14
【问题描述】:
我目前正在阅读 wikibooks 中的 Alternative/MonadPlus 类型类。它很好地描述了差异。然而,一个令人费解的部分是guard 函数,我假设它用于“短路”计算。 (我说的对吗?)
虽然在Control.Monad 中定义了函数guard,但它具有Alternative 约束,如下所示(link)。
guard :: (Alternative f) => Bool -> f ()
guard True = pure ()
guard False = empty
但上面的文章提到,只需要MonadPlus 来执行左零和右零定律(因此更有力的主张)。
mzero >>= f = mzero -- left zero
m >> mzero = mzero -- right zero
鉴于guard 函数的用途,不应该用MonadPlus 约束来定义它吗?如果guard 应该“短路”计算,我们不需要更严格的法律吗?我很好奇具体设计选择背后的原因。
p.s.:除了“短路”这个词,我不知道还有什么更好的方式来描述“取消前期计算”行为?
【问题讨论】:
-
MonadPlus比Alternative强,你不需要MonadPlus来写guard-Alternative的类型是最通用的类型,即推断的类型。为什么要给它一种更强的类型? (注意 wikibooks 页面在 AMP 之后已经过时,所以 ghc 8 及更高版本?我实际上不记得了..) -
@user2407038 如果守卫应该做“短路”,我们不需要更强大的法律(左零,右零)吗?
-
您在
Applicative上下文中得到“短路”:guard False *> x = empty和guard True *> x = x;它同样适用于Monad,就像所有适用于Applicative的东西都适用于Monad。 -
@user2407038 但是 AFAIK
Alternative并没有强制执行empty *> x == empty法律。所以它可能不适用于所有实例。我说的对吗? -
这是一个文档问题。
guard是MonadPlus m => ...,但现在每个MonadPlus都是Alternative,默认情况下是mzero = empty和mplus = (<|>)。因此,如果您有一个既是Monad又是Alternative的类型,它应该遵守这些定律。但是,这应该在class Alternative或class Monad文档中说明。话虽如此,guard的功能并没有减少。mzero在所有常见的MonadPlus实例上是empty。
标签: haskell monads alternative-functor monadplus