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

尽管在guard中定义了函数Control.Monad,但它具有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应该“短路”计算,我们是否不需要更严格的定律?我对特定设计选择背后的原因感到好奇。

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

最佳答案

guard具有Applicative约束,因为您不需要对其执行单子(monad)运算来定义函数。

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

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

如果它指定了MonadPlus而不是Alternative,那么它什么也得不到。 MonadPlusAlternative的子类,因此所有MonadPlus实例都可以使用guard,但并非所有Alternatives都可以使用它。

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

通常,最好坚持编写函数所需的最低限度限制,即使预期用途更加具体。这样一来,没有什么不应该被排除在外,也没有来自那些类型适合它但不是单子(monad)的人的提示。

巧合的是,Hoogle search results错误地显示了MonadPlus限制,尽管如果您单击链接,它是正确的。

关于haskell - 为什么 `guard`没有用MonadPlus约束定义?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42037064/

10-13 03:09