为什么`guard`没有用MonadPlus约束定义?

zer*_*one 5 monads haskell

我目前正在读关于另类/ MonadPlus类型类维基教科书.它很好地描述了这种差异.然而,一个令人费解的部分是guard我假设的函数用于"短路"计算.(我对吗?)

guard虽然定义的函数Control.Monad有一个Alternative约束,如下(链接).

guard           :: (Alternative f) => Bool -> f ()
guard True      =  pure ()
guard False     =  empty
Run Code Online (Sandbox Code Playgroud)

但是上面的文章提到只MonadPlus需要强制执行左零和零零定律(因此更强的主张).

mzero >>= f  =  mzero -- left zero
m >> mzero   =  mzero -- right zero
Run Code Online (Sandbox Code Playgroud)

鉴于guard函数的目的,不应该用MonadPlus约束来定义它吗?如果guard应该"短路"计算,我们不需要更强的定律吗?我很好奇特定设计选择背后的原因.

ps:我不知道什么是比"短路"这个词更好的描述"取消前期计算"行为的方法?

zbw*_*zbw 0

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

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

guard           :: (Alternative f) => Bool -> f ()
guard True      =  pure ()
guard False     =  empty
Run Code Online (Sandbox Code Playgroud)

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

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

一般来说,最好坚持编写函数所需的最低限制,即使预期用途更具体。这样,就不会出现任何不应该被排除的情况,也不会出现那些类型可以适用但不是 monad 的人的抱怨。

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