为什么guard基于Alternative?
guard :: Alternative f => Bool -> f ()
-- guard b is pure () if b is True,
-- and empty if b is False.
Run Code Online (Sandbox Code Playgroud)
我问因为guard只使用了empty来自Alternative.它不使用<|>从Alternative根本.那么为什么要Alternative首先使用呢?
我想这是因为背后有一些不成文的想法Alternative的empty,与我们正在努力与实现的目标完全吻合guard(停止False,继续True).如果是这种情况,请告诉我这个没有说明的想法.
但与此同时,如果觉得我们只是在忽视<|>.感觉好像guard不是"完全捕捉"到底Alternative是什么.我希望这是有道理的.为了使它更具体:为什么他们不发明另一个类似Stoppable(或Abortable)之类的类型并使用它而不是Alternative?
TL; DR:历史原因.有人设想这样的MonadPlus,它有它的Applicative变种Alternative以后,也没有人提出分割Alternative成AZero和AChoice或相似.
Alternative是一个相对较新的想法,就像Applicative.回到guard最初设想时,它是基于MonadPlus,一个Monad应该支持选择和失败,就像Alternative.因此它的原始类型
guard :: MonadPlus m => Bool -> m ()
Run Code Online (Sandbox Code Playgroud)
这已经在Haskell 98报告中指出,MonadPlus已经注意到了.顺便说一下,Haskell 1.0根本没有使用monad.当Applicative最后得到一个超类时Monad,Alternative得到了一个超类MonadPlus,mzero = empty和mplus = (<|>).
那么,现在我们知道为什么guard用了Alternative.因为它是MonadPlus事先制定的.那么为什么这样MonadPlus定义呢?
人们不得不写一封邮件给SPJ或委员会中的其他人从1998年开始获得他们的理由,因为仅仅一年之后,Erik Meijer和Graham Hutton写了他们的"Haskell中的Monadic Parsing"论文.如果你看一下这篇论文,你会发现它们的 MonadPlus正常工作就像你想要的那样:
Run Code Online (Sandbox Code Playgroud)class Monad m => MonadZero m where zero :: m a class MonadZero m => MonadPlus m where (++) :: m a -> m a -> m a
因此,按照你所描述的方式处理这种"可停止"肯定是可能的.但是,目前没有任何base类empty没有Alternative.可能有一个,但尚未提出.
请注意,这是Haskell类的重复主题.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)
Run Code Online (Sandbox Code Playgroud)
在这里,mappend = combine显然是关联的,而Min如果我们只是使用Ord,则无法使用空,我们将不得不使用Bounded.这就是为什么现在Semigroup,它还不是一个基类Monoid,但给了我们联想操作.
回到你原来的问题:guard使用Alternative,因为Alternative提供empty,并empty"停止"某些Alternative人的评价.有包含,没有其他类还.
但是有了提案,可能会在某个时候,虽然我不确定社群对分裂的看法Alternative是什么.
顺便说一句,像PureScript这样的语言会分裂Alternative,尽管它们会以相反的方式将它分开......
有关Alternative我用作Monoid另一个示例的更多信息和原因,请参阅"Alternative"类型类的含义及其与其他类型类的关系.
| 归档时间: |
|
| 查看次数: |
309 次 |
| 最近记录: |