Parsing Haskell解析:x++;y:z

Parsing Haskell解析:x++;y:z,parsing,haskell,Parsing,Haskell,在Haskell中,为什么x++y:z被解析为x++(y:z),而不是(x++y):z 例如,[1]++2:[3]的计算结果为[1,2,3] (++)和(:)都是优先顺序为5的右关联。它们是右关联的这一事实意味着可以说它们是“从右到左”解析的。这意味着x⊕ Y⊕ z被解析为x⊕ (y)⊕ z) 。这意味着x++y:z确实被解析为x++(y:z) 有充分的理由使(:)和(++)正确关联。对于“cons”(:)运算符,这意味着我们可以编写1:4:2:[],因为它被解析为1:(4:(2:[]),这在类

在Haskell中,为什么
x++y:z
被解析为
x++(y:z)
,而不是
(x++y):z

例如,
[1]++2:[3]
的计算结果为
[1,2,3]


(++)
(:)
都是优先顺序为5的右关联。

它们是右关联的这一事实意味着可以说它们是“从右到左”解析的。这意味着x⊕ Y⊕ z被解析为x⊕ (y)⊕ z) 。这意味着
x++y:z
确实被解析为
x++(y:z)

有充分的理由使
(:)
(++)
正确关联。对于“cons”
(:)
运算符,这意味着我们可以编写
1:4:2:[]
,因为它被解析为
1:(4:(2:[])
,这在类型方面是正确的。如果像
((1:4):2:[])
那样解析它,那么
1:4
将是错误的,因为它期望一个项作为第一个操作数,而这些项的列表作为第二个操作数。当然,我们仍然可以让Haskell解析器将其解析为一个列表,但这将导致大量额外的括号


对于
(++)
,由于性能原因,最好从右向左解析它
x++y
采用
x
大小的线性时间。这意味着如果我们解析
x++(y++z)
,它将采取| x |+| y |步骤。如果我们将其解析为
(x++y)++z
,则需要2×|x++y |,因为我们第一次应用
(x++y)
时,它以
x
的大小运行,但
(x++y)++z
x++y
的大小运行。因此,这意味着如果我们将n个列表串联起来,每个列表的大小为m,它将不会在O(n×m)中运行,而是在O(n2×m)中运行。

您没有回答自己的问题吗?由于它们具有相同优先级的右关联性,因此表达式是从右而不是从左求值的。我不清楚的事实是,Haskell中的关联性不仅用于消除形式x表达式的歧义,而且从您的回答中也不完全清楚⊕Y⊕但也可以消除形式x表达式的歧义⊕Y⊗z何时⊕ 及⊗ 具有相同的优先级和关联性。引用Haskell 2010年的报告:“具有相同优先级的连续未解析运算符必须是左关联或右关联的,以避免语法错误。”@user188895:是的,如果具有相同的优先级,这意味着它们是从右向左解析的(也使用“混合”运算符,如您在注释中所示)。请注意,运算符的关联性必须相同,正如Haskell报告中所述:“具有相同优先级的连续未关联运算符必须是左关联或右关联的,以避免语法错误。”(第3章)。