6

我目前正在阅读 wikibooks 中的 Alternative/MonadPlus 类型。它很好地描述了差异。然而,一个令人费解的部分是guard我假设的函数用于“短路”计算。(我对吗?)

该函数guard虽然在中定义,但Control.Monad有一个Alternative约束,如下所示(链接)。

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如果应该“短路”计算,我们是否不需要更强大的法律?我很好奇具体设计选择背后的原因。

ps:我不知道除了“短路”这个词之外,还有什么更好的方式来描述“取消前期计算”的行为?

4

1 回答 1

0

guard有一个Applicative约束,因为您不需要对其执行单子操作来定义函数。

它的定义是(从Hackage 源复制而来):

guard           :: (Alternative f) => Bool -> f ()
guard True      =  pure ()
guard False     =  empty

如果它指定MonadPlus而不是Alternative,它不会获得任何东西。 MonadPlus是 的子类Alternative,因此所有MonadPlus实例都可以使用guard,但并非所有人都Alternatives可以使用它。

(尽管很少有被排除的情况——这里Alternatives提到的两种情况都有一个例子,即使它们不满足左分配规则。)MonadPlus

一般来说,最好坚持编写函数所需的最低限度的限制,即使预期用途更具体。这样一来,就没有什么不应该被排除在外了,也没有来自那些可以为它工作但不是单子的人的抱怨。

巧合的是,Hoogle 搜索结果错误地显示了MonadPlus限制,但如果您单击链接,它是正确的。

于 2017-04-17T23:57:15.350 回答