Haskell的<|>运算符有什么作用?

Ele*_*fee 65 haskell applicative

通过Haskell的文档对我来说总是有点痛苦,因为你获得的关于函数的所有信息通常只是:f a -> f [a]它可能意味着任何数量的东西.

<|>功能的情况一样.

我给的只是这个:(<|>) :: f a -> f a -> f a它是一个"联想二元运算" ......

经过检查,Control.Applicative我了解到,根据实施情况,它看似无关紧要.

instance Alternative Maybe where
    empty = Nothing
    Nothing <|> r = r
    l       <|> _ = l
Run Code Online (Sandbox Code Playgroud)

好的,所以如果没有剩下它就会返回,否则它会返回left,gotcha ..这让我相信它是一个"左或右"操作符,鉴于它的使用||历史用途为"OR ",这有点意义"

instance Alternative [] where
    empty = []
    (<|>) = (++)
Run Code Online (Sandbox Code Playgroud)

除了这里它只是调用list的连接运算符...打破我的想法......

那究竟是什么功能呢?有什么用?在宏伟的计划中它适合哪里?

J. *_*son 66

通常,它的意思是"选择"或"平行",因为a <|> b是的任一个"选择" abab并行完成.但是让我们回来吧.

实际上,类似(<*>)或类的类型操作没有实际意义(<|>).这些操作以两种方式赋予意义:(1)通过法则和(2)通过实例化.如果我们不是在谈论特定的实例Alternative那么只有(1)可用于直觉意义.

所以"联想"意味着与之a <|> (b <|> c)相同(a <|> b) <|> c.这很有用,因为它意味着我们只关心链接在一起的事物的序列(<|>),而不是它们的"树结构".

其他法律包括身份empty.特别是a <|> empty = empty <|> a = a.在我们与"选择"或"平行"这些法律解读为直觉"一(什么是不可能的),必须是"或"旁边(空过程)只是一个".它表明empty是某种"失败模式" Alternative.

还有其他法则与(from )或/ (from )如何(<|>)/ empty相互作用,但也许在理解其含义方面向前推进的最佳方法是检查实例化的类型的一个非常常见的例子:a .fmapFunctorpure(<*>)Applicative(<|>)AlternativeParser

如果x :: Parser Ay :: Parser B(,) <$> x <*> y :: Parser (A, B)分析x ,然后 y按顺序排列.相比之下,(fmap Left x) <|> (fmap Right y)解析无论是 xy,与开始x,尝试两种可能的解析.换句话说,它表示解析树中的分支,选择或并行解析Universe.

  • @ElectricCoffee这不是严格意义上的.例如,首先考虑类型[`ZipList a`](http://hackage.haskell.org/package/base-4.7.0.1/docs/Control-Applicative.html#t:ZipList)基本上与`[一个]`.现在`[(+ 1),(+ 2)] <*> [1,2] = [2,3,3,4]`而`ZipList [(+ 1),(+ 2)] <*> ZipList [1,2] = ZipList [2,4]`.因此,并不总是如此完全清楚`(<*>)`应该是什么意思. (3认同)

Ben*_*Ben 35

(<|>) :: f a -> f a -> f a实际上告诉你很多,即使没有考虑到法律Alternative.

它需要两个f a值,并且必须返回一个.所以它必须以某种方式组合或选择其输入.它在类型多态a,所以这将是完全无法检查任何类型的值a可能是内部的f a; 这意味着它不能通过组合a值来进行"组合" ,因此它必须纯粹根据类型构造函数f添加的任何结构来实现.

这个名字也有点帮助.某种"OR"确实是作者试图用"Alternative"和"<|>"这个名称来表示的模糊概念.

现在,如果我有两个Maybe a值,我必须将它们组合在一起,我该怎么办?如果他们俩都是Nothing必须返回Nothing,没有办法来创建一个a.如果它们中至少有一个是Just ...我可以按原样返回我的一个输入,或者我可以返回Nothing.很少有函数甚至可以使用类型Maybe a -> Maybe a -> Maybe a,对于名为"Alternative"的类,给出的是非常合理和明显的.

如何组合两个[a]值?这里有更多可能的功能,但实际上很明显这可能是什么.如果您熟悉标准monad/applicative的标准"非确定性"解释,那么"Alternative"这个名称确实可以为您提供一个很好的暗示.如果你看到一个具有可能值集合的[a]"非确定性a",那么a以一种可能值得称之为"替代"的方式"组合两个非确定性值" 的明显方法是产生一个非确定性的a,它可以是任何值来自任何一个输入.

对于解析器; 结合两个解析器有两个明显的广泛解释,浮现在脑海中; 要么你产生一个与第一个匹配的解析器,然后是第二个做什么的解析器,要么你产生一个解析器,它匹配第一个做什么第二个做什么(当然,每个选项的细微细节都会留下选择的余地).鉴于"替代"这个名称,"或"解释似乎非常自然<|>.

所以,从一个足够高的抽象层次看出,这些操作都"做同样的事情." 类型类实际上是在高抽象级别操作,这些东西都"看起来一样".当我在一个已知的实例上运行时,我只是将<|>操作视为它对该特定类型的确切操作.

  • 这些成分仅仅是类型类的名称、运算符的类型签名和特定实例的一些具体示例。结果是理解“Alternative”类型类的秘诀。我想知道这种方法是否足以解释其他广义的 FP 概念。谢谢! (2认同)

Mat*_*hid 13

这些似乎非常不同,但考虑:

Nothing <|> Nothing == Nothing
     [] <|>      [] ==      []

Just a  <|> Nothing == Just a
    [a] <|>      [] ==     [a]

Nothing <|> Just b  == Just b
     [] <|>     [b] ==     [b]
Run Code Online (Sandbox Code Playgroud)

所以......这些实际上非常非常相似,即使实现看起来不同.唯一真正的区别在于:

Just a  <|> Just b  == Just a
    [a] <|>     [b] ==     [a, b]
Run Code Online (Sandbox Code Playgroud)

A Maybe只能容纳一个值(或零,但不能容纳任何其他数量).但是,嘿,如果它们都是相同的,你为什么需要两种不同的类型?你知道,他们的不同之处在于它们是不同的.

总之,实现可能看起来完全不同,但实际上它们非常相似.


dan*_*iaz 12

一个有趣的例子Alternative不是解析器或类似MonadPlus的东西Concurrently,是async包中非常有用的类型.

因为Concurrently,empty是一个永远持续的计算.而(<|>)同时执行它的参数,返回完成了第一次的结果,并取消另一个.