为什么我不能在与Control.Arrow.(>>>)
相同的表达式中使用Data.Function.(&)
?
在F#中花了很多时间之后,我正在学习Haskell,我发现从右到左的表示法让我很难理解更长的管道。(我知道这不是惯用语(
我读到&
和>>>
是F#的|>
和>>
的Haskell等价物。然而,这失败了:
[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]
显然没有。
它不是"优先级错误";,它是";优先级解析错误";(重点是我的(。
如果我们在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
因此,如果右边有一长串与>>>
相连的表达式,则parens更紧密,整个表达式可能更可读。
&
具有单独链接的正确优先级:
[1..10] & take 5 & sum
这里不需要>>>
,而且&
和>>>
不是共同设计的,所以它们的优先级并不适合这个用例。