3

为什么我不能Data.Function.(&)在与 相同的表达式中使用Control.Arrow.(>>>)

在 F# 中花了很多时间后,我正在学习 Haskell,我发现从右到左的符号很难理解更长的管道。(我知道这不是惯用的)

我读过它,&并且>>>Haskell 相当于 F#|>>>. 但是,这失败了:

[someList] & take 5 >>> sum

带有“优先级错误”:

Prelude Data.Function Control.Arrow> [1:10] & take 5 >>> sum
<interactive>:4:1: error:
    Precedence parsing error
        cannot mix `&' [infixl 1] and `>>>' [infixr 1] in the same infix expression

尽管

sum . take 5 $ [someList]

显然没有。

4

2 回答 2

4

这不是“优先级错误”,而是“优先级解析错误”(强调我的)。

如果我们在 GHCi 中尝试它,> :i &回复为infixl 1 &,而> :i >>>回复为infixr 1 >>>.

因此,一个 ( &) 在左边 ( infixl) 上加上括号,另一个 ( >>>) 在右边 ( infixr) 上。

具有较高优先级的将获胜,但这两个具有相同的优先级(1)。这就是错误消息告诉我们的(有点不恰当):

    Precedence parsing error
        cannot mix `&' [infixl 1] and `>>>' [infixr 1] in the same infix expression

意味着,因为它们具有相同的优先级,在这个表达式中混合在一起的这些左关联和右关联中缀运算符的解析是模棱两可的,因此是不可能的。

所以你最终不得不使用显式括号来正确解析这个表达式:

[someValue] & (take 5 >>> sum)

顺便说一句,[someValue]已经是一个列表。因为你使用sum它的一个元素的类型必须在Num( someValue :: Num a => a, [someValue] :: Num a => [a]) 中。

但是如果你宁愿已经有someList几个数值(someList :: Num a => [a]),你只需写

someList & (take 5 >>> sum)

因为[someList]是一个包含单个值的列表,它恰好是一个数字列表(大概)。所以[someList]这个表达式无论如何都行不通:

> [5] & (take 5 >>> sum)
5

> [[3,4,5]] & (take 5 >>> sum)

<interactive>:431:1:
    No instance for (Num [t0]) arising from a use of `it'
    In a stmt of an interactive GHCi command: print it

使其解析的另一种方法是在左侧使用显式括号

(someList &) $ take 5 >>> sum

>>>因此,如果您在右侧有很长的表达式链,则括号更靠近,整个表达式可能更具可读性。

于 2021-11-08T13:04:06.210 回答
3

&具有被自己链接的正确优先级:

[1..10] & take 5 & sum

您在这里不需要>>>任何东西,并且&没有>>>共同设计,因此它们的优先级并不真正适合这个用例。

于 2021-11-08T08:12:35.400 回答