为什么守卫基于替代? [英] Why is guard based on Alternative?

查看:53
本文介绍了为什么守卫基于替代?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么 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 ?

I ask because guard only uses the empty from Alternative. It doesn't use <|> from Alternative at all. So why bother using Alternative in the first place?

我猜这是因为 Alternative empty 背后有一些未阐明的想法,与我们正在尝试使用 guard 完成的任务完全匹配代码>(在 False 上停止,在 True 上继续).如果是这种情况,请向我介绍这个未阐明的想法.

I guess this is because there is some unstated idea behind Alternative's empty that matches perfectly with what we're trying to accomplish with guard (stop on False, continue on True). If this is the case, please enlighten me about this unstated idea.

同时,如果感觉到我们只是忽略了< |> .感觉好像 guard 并没有完全捕获" Alternative 的全部含义.我希望这是有道理的.更具体地说:他们为什么不发明另一个类型类,称为 Stoppable (或 Abortable ),并使用它代替 Alternative ?

Yet at the same time, if feels that we're just ignoring <|>. It feels almost as if guard is not "fully capturing" what Alternative is all about. I hope that makes sense. To make it more concrete: Why didn't they invent another type class called something like Stoppable (or Abortable) and used that instead of Alternative?

推荐答案

TL; DR:历史原因.在 MonadPlus 中对此进行了设想,后来又得到了 Applicative 变体 Alternative ,并且没有人建议拆分 Alternative AZero AChoice 或类似的代码中.

TL;DR: Historical reasons. It was envisioned like this in MonadPlus, which got its Applicative variant Alternative later, and no one has proposed to split Alternative into AZero and AChoice or similar.

Alternative 是一个相对的新概念.回到最初设想 guard 时,它是基于

Alternative is a relatively new idea, just like Applicative. Back when guard was first envisioned, it was based on MonadPlus, a Monad that should support choice and failure, just like Alternative. Its original type was thus

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

这是在Haskell 98报告中指定的,其中 MonadPlus 已经被注意到.顺便说一下,Haskell 1.0根本不使用monad.当 Applicative 最终获得 Monad 的超类时, Alternative 得到 MonadPlus 的超类,并且 mzero =空 mplus =(< |>).

That was specified in the Haskell 98 report, where MonadPlus was already noted. Haskell 1.0 didn't use monads at all, by the way. When Applicative finally got a superclass of Monad, Alternative got a superclass of MonadPlus, and mzero = empty and mplus = (<|>).

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

Well, now we know why guard uses Alternative. Because it was based on MonadPlus beforehand. So why is MonadPlus defined like this?

一个人必须写一封信给SPJ或委员会的其他人,以获取1998年的依据,因为仅仅一年后,论文.如果您看一下这篇论文,您会发现他们的 MonadPlus 的工作原理与您预期的一样:

One would have to write a mail to SPJ or someone else from the committee to get their rationale from 1998, because just one year later, Erik Meijer and Graham Hutton wrote their "Monadic Parsing in Haskell" paper. If you have a look at the paper, you'll notice that their MonadPlus just works like you intend:

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

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

因此,一定可以用您描述的方式来处理可停止的"事件.但是,根本没有 base 类当前没有 Alternative 的情况下定义了 empty 的类.可能有一个,但尚未提出.

So it's certainly possible to handle this "stoppable" the way you've described it. However, there is simply no base class that currently defines empty without Alternative. There could be one, but it wasn't proposed yet.

请注意,这是Haskell类的重复主题. Monoid 包含 mappend mempty .在构思之后,有人注意到,在某些类型中, mappend 是有意义的,而对于 mempty 则没有意义.例如

Note that this is a recurring theme with Haskell classes. Monoid contains mappend and mempty. After its conception, someone noticed that there are certain types where mappend makes sense, but not mempty. For example

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 显然是关联的,而如果仅使用 Ord ,则不可能有空的 Min 使用 Bounded .这就是为什么现在有 Semigroup ,它不是 Monoid 的基类,但是为我们提供了关联操作.

Here, mappend = combine is clearly associative, whereas an empty Min isn't possible if we just use Ord, we would have to use Bounded. That's why there is now Semigroup, which isn't a base class of Monoid yet, but gives us that associative operation.

回到您最初的问题: guard 使用 Alternative ,因为 Alternative 提供了 empty empty 在某些 Alternative 中停止"评估.没有其他包含 的类.

To come back to your original question: guard uses Alternative, because Alternative provides empty, and empty "stops" the evaluation in certain Alternative's. There's no other class that contains that, yet.

但是有一个建议,也许会在某个时候出现,尽管我不确定社区对拆分 Alternative 的看法是什么.

But with a proposal, there might be at some point, although I'm not sure what's the community's opinion on splitting Alternative is.

顺便说一下,像PureScript这样的语言会拆分 Alternative ,尽管它们是将其拆分的另一种方式……

By the way, languages like PureScript split Alternative, although they split it the other way round…

有关 Alternative 以及为什么使用 Monoid 作为另一个示例的更多信息,请参见.

For more information about Alternative and why I used Monoid as another example, see Confused by the meaning of the 'Alternative' type class and its relationship to other type classes.

这篇关于为什么守卫基于替代?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆