为什么`guard`基于`Alternative`?

时间:2017-06-22 10:35:36

标签: haskell

为什么guard基于Alternative

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

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

我想这是因为Alternative&#39; empty背后有一些未说明的想法与我们guard要完成的事情完全匹配(停止在False,继续True)。如果是这种情况,请告诉我这个没有说明的想法。

但与此同时,如果觉得我们只是忽略了<|>。感觉好像guard没有&#34;完全捕捉&#34; Alternative的全部内容。我希望这是有道理的。为了使它更具体:为什么他们没有发明另一个类似Stoppable(或Abortable)的类型,而是使用它而不是Alternative

1 个答案:

答案 0 :(得分:8)

TL; DR:历史原因。在MonadPlus中设想这样,后来获得了Applicative变体Alternative,并且没有人建议将Alternative分成AZero和{{1}或类似的。

AChoice相对的新想法,就像Alternative一样。在第一次设想Applicative时,它基于MonadPlusguard应该支持选择和失败,就像Monad一样。因此它的原始类型是

Alternative

这是在Haskell 98报告中指定的,其中已注明MonadPlus。顺便说一下,Haskell 1.0根本没有使用monad。当guard :: MonadPlus m => Bool -> m () 最终获得Applicative的超类时,Monad获得了AlternativeMonadPlusmzero = empty的超类。

好吧,现在我们知道为什么mplus = (<|>)使用guard。因为它事先基于Alternative。那么为什么MonadPlus被定义为这样?

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

MonadPlus

所以它当然有可能处理这个&#34;可停止的&#34;你描述它的方式。但是,目前只有class Monad m => MonadZero m where zero :: m a class MonadZero m => MonadPlus m where (++) :: m a -> m a -> m a 类没有base而没有empty。可能有一个,但尚未提出。

请注意,这是Haskell类的重复主题。 Alternative包含Monoidmappend。在构思之后,有人注意到某些类型mempty有意义但不是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提供emptyempty&#34;停止&#34;某些Alternative的评估。没有其他类包含

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

顺便说一下,像PureScript这样的语言会分割Alternative,尽管它们会反过来分开......

有关Alternative以及我使用Monoid的原因的详细信息,请参阅Confused by the meaning of the 'Alternative' type class and its relationship to other type classes