【问题标题】:Why `guard` is not defined with a MonadPlus constraint?为什么 `guard` 没有用 MonadPlus 约束定义?
【发布时间】: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.:除了“短路”这个词,我不知道还有什么更好的方式来描述“取消前期计算”行为?

【问题讨论】:

  • MonadPlusAlternative 强,你不需要MonadPlus 来写guard - Alternative 的类型是最通用的类​​型,即推断的类型。为什么要给它一种更强的类型? (注意 wikibooks 页面在 AMP 之后已经过时,所以 ghc 8 及更高版本?我实际上不记得了..)
  • @user2407038 如果守卫应该做“短路”,我们不需要更强大的法律(左零,右零)吗?
  • 您在Applicative 上下文中得到“短路”:guard False *> x = emptyguard True *> x = x;它同样适用于Monad,就像所有适用于Applicative 的东西都适用于Monad
  • @user2407038 但是 AFAIK Alternative 并没有强制执行 empty *> x == empty 法律。所以它可能不适用于所有实例。我说的对吗?
  • 这是一个文档问题。 guardMonadPlus m => ...,但现在每个 MonadPlus 都是 Alternative,默认情况下是 mzero = emptymplus = (<|>)。因此,如果您有一个既是 Monad 又是 Alternative 的类型,它应该遵守这些定律。但是,这应该在class Alternativeclass Monad 文档中说明。话虽如此,guard 的功能并没有减少。 mzero 在所有常见的 MonadPlus 实例上是 empty

标签: haskell monads alternative-functor monadplus


【解决方案1】:

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

它的定义是(复制自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 限制,但如果您点击链接,它是正确的。

【讨论】:

  • AFAIK 该函数是使用 MonadPlus 约束定义的,后来更改为 Applicative。
猜你喜欢
  • 1970-01-01
  • 2012-11-28
  • 1970-01-01
  • 1970-01-01
  • 2020-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-11
相关资源
最近更新 更多