为什么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
?
答案 0 :(得分:8)
TL; DR:历史原因。在MonadPlus
中设想这样,后来获得了Applicative
变体Alternative
,并且没有人建议将Alternative
分成AZero
和{{1}或类似的。
AChoice
是相对的新想法,就像Alternative
一样。在第一次设想Applicative
时,它基于MonadPlus
,guard
应该支持选择和失败,就像Monad
一样。因此它的原始类型是
Alternative
这是在Haskell 98报告中指定的,其中已注明MonadPlus
。顺便说一下,Haskell 1.0根本没有使用monad。当guard :: MonadPlus m => Bool -> m ()
最终获得Applicative
的超类时,Monad
获得了Alternative
,MonadPlus
和mzero = 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
包含Monoid
和mappend
。在构思之后,有人注意到某些类型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
提供empty
,empty
&#34;停止&#34;某些Alternative
的评估。没有其他类包含 。
但是有了提案,可能会在某个时候,虽然我不确定社群对于分割Alternative
的看法是什么。
顺便说一下,像PureScript这样的语言会分割Alternative
,尽管它们会反过来分开......
有关Alternative
以及我使用Monoid
的原因的详细信息,请参阅Confused by the meaning of the 'Alternative' type class and its relationship to other type classes。