【问题标题】:Why is guard based on Alternative?为什么Guard基于Alternative?
【发布时间】:2017-06-22 10:35:35
【问题描述】:

为什么guard是基于Alternative

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

我问是因为guard 只使用来自Alternativeempty。它根本不使用来自Alternative<|>。那么为什么要首先使用Alternative呢?

我猜这是因为Alternativeempty 背后有一些未说明的想法,这与我们试图通过guard 完成的目标完全匹配(停止False,继续True) .如果是这种情况,请告诉我这个未说明的想法。

同时,如果觉得我们只是忽略了<|>。感觉就像guard 没有“完全捕捉”Alternative 的全部内容。我希望这是有道理的。更具体地说:他们为什么不发明另一个类型类,称为Stoppable(或Abortable)并使用它而不是Alternative

【问题讨论】:

  • 您还需要pure。当然,您可以有一个提供purePure 类和一个提供emptyEmpty 类,并且让Alternative 两者都需要。但是,出于务实的原因,并不总是将一个类拆分为单一方法的类。
  • 这种情况下是实际原因还是历史原因?
  • 我认为是因为没有类型,可以实现empty,不能实现(<|>)。因此,理论上类型类 Stoppable 将等于 Alternative(类型集将相等)。
  • @freestyle: 好笑,PureScript 通过Plus(提供empty)定义Alternative,它是基于Alt(提供(<|>))。所以他们遵循 Semigroup/Monoid 方法。

标签: haskell alternative-functor


【解决方案1】:

TL;DR:历史原因。在MonadPlus 中是这样设想的,后来得到了它的Applicative 变体Alternative,并且没有人提议将Alternative 拆分为AZeroAChoice 或类似的。


Alternative 是一个相对的新想法,就像Applicative 一样。回到最初设想guard 的时候,它基于MonadPlus,一个应该支持选择和失败的Monad,就像Alternative 一样。它原来的类型是这样的

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

这是在 Haskell 98 报告中指定的,其中 MonadPlus 已被注明。顺便说一句,Haskell 1.0 根本没有使用 monad。当Applicative 最终得到Monad 的超类时,Alternative 得到了MonadPlusmzero = 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

因此,按照您描述的方式处理这种“可停止”当然是可能的。但是,目前根本没有base 类在没有Alternative 的情况下定义empty。可能有一个,但尚未提出。

请注意,这是 Haskell 类中反复出现的主题。 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 的基类,但给了我们关联操作。

回到你原来的问题:guard 使用Alternative,因为Alternative 提供empty,而empty“停止”某些Alternative 的评估。没有其他类包含它,

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

顺便说一句,像 PureScript 之类的语言拆分 Alternative,虽然他们拆分它的方式相反......

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

【讨论】:

  • 我不会说这本身就是一个疏忽。在粒度和内聚性之间存在合理的设计权衡。与 PureScript 相比,我个人更喜欢 Haskell 类层次结构。 empty<|> 以一种自然的方式“走在一起”。
  • @BenjaminHodgson 我删除了判断,这不太合适。
  • MonadFail 也值得考虑,他的fail 有点像empty,但它用>>= 扩展了空虚而不是恢复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-02
  • 2012-12-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多