为什么guard是基于Alternative的?

Why is guard based on Alternative?

为什么 guard 基于 Alternative

guard :: Alternative f => Bool -> f ()
-- guard b is pure () if b is True,
-- and empty if b is False.

我问是因为 guard 只使用 Alternative 中的 empty。它根本不使用 Alternative 中的 <|>。那么,为什么要首先使用 Alternative 呢?

我想这是因为 Alternativeempty 背后有一些未说明的想法,它与我们试图通过 guard 实现的目标完美匹配(停在 False,继续 True)。如果是这样的话,请赐教这个未明说的想法。

但与此同时,如果感觉我们只是在忽略 <|>。感觉好像 guard 不是 "fully capturing" Alternative 的全部内容。我希望这是有道理的。更具体地说:为什么他们不发明另一种类型 class 称为 Stoppable(或 Abortable)并使用它来代替 Alternative

TL;DR: 历史原因。在MonadPlus中是这样设想的,后来得到了它的Applicative变体Alternative,也没有人提议将Alternative拆分成AZero和[=18] =] 或类似的。


AlternativeApplicative一样,是相对的新点子。当 guard 最初设想时,它是基于 MonadPlus,一个应该支持选择和失败的 Monad,就像 Alternative 一样。因此它的原始类型是

guard :: MonadPlus m => Bool -> m ()

这在 Haskell 98 报告中已指定,其中 MonadPlus 已注明。 Haskell 顺便说一下,1.0 根本没有使用 monad。当Applicative终于得到了一个Monad的superclass,Alternative得到了一个MonadPlus的superclass,而mzero = emptymplus = (<|>).

好了,现在我们知道为什么 guard 使用 Alternative 了。因为它是事先基于 MonadPlus 的。那么为什么MonadPlus是这样定义的呢?

人们必须写一封邮件给 SPJ 或委员会的其他人才能从 1998 年获得他们的理由,因为仅仅一年后,Erik Meijer and Graham Hutton wrote their "Monadic Parsing in Haskell" 论文。如果你看一下这篇论文,你会注意到 他们的 MonadPlus 就像你想要的那样工作:

class Monad m => MonadZero m where
  zero :: m a

class MonadZero m => MonadPlus m where
  (++) :: m a -> m a -> m a

因此,"stoppable"当然可以按照您描述的方式处理此问题。但是,没有 base class 当前定义没有 Alternativeempty。可能有一个,但尚未提出。

请注意,这是一个包含 Haskell class 的重复主题。 Monoid 包含 mappendmempty。在其构想之后,有人注意到某些类型 mappend 有意义,但 mempty 没有意义。例如

newtype Min a = Min a

combine :: Ord a => Min a -> Min a -> Min a
combine (Min x) (Min y) = Min (min x y)

这里,mappend = combine显然是关联的,而空的Min如果我们只使用Ord是不可能的,我们必须使用Bounded。这就是为什么现在有 Semigroup,它还不是 Monoid 的基础 class,但是给了我们那个关联操作。

回到您原来的问题:guard 使用 Alternative,因为 Alternative 提供 empty,而 empty "stops"某些 Alternative 中的评估。没有其他 class 包含那个,

但是有了提案,在某个时候可能会有,尽管我不确定社区对拆分 Alternative 的看法是什么。

顺便说一句,像 PureScript 这样的语言分裂了 Alternative,尽管它们以相反的方式分裂了……

有关 Alternative 的更多信息以及为什么我使用 Monoid 作为另一个示例,请参阅 Confused by the meaning of the 'Alternative' type class and its relationship to other type classes