我试图弄清楚 Haskell 中的优先级规则。 当我写代码行“f a b”时,它会被解释为 (f a) b,即使用左关联机制。
但是让我们想象一下,我正在用 Haskell 编写一个计算斐波那契数列项的函数。然后我运行以下程序:
fibo 0 = 1
fibo 1 = 1
fibo n = fibo(n-1) + fibo(n-2)
对于最后一个表达式,这将被解释为:
(((fibo(n-1))+)fibo)(n-2))
为什么取第二个fibo没有报错。在结果作为函数 (+) 的参数给出之前,编译器如何知道 fibo 必须应用于 (n-2)?跟算术运算符有关吗?
我在 ghci 和语法上尝试了很多测试
g = fibo 2 + fibo
不被接受。
对于最后一个表达式,这将被解释为:
(((fibo(n-1))+)fibo)(n-2))
那完全不正确。
函数应用程序比 any 运算符具有更高的优先级。
fibo (n - 1) + fibo (n - 2)
相当于
(fibo (n - 1)) + (fibo (n - 2))
请注意,括号不是函数调用语法的一部分;表达
fibo n - 1
仍然是一个函数应用,但是它把
fibo n
的结果减1,和(fibo n) - 1
一样。
Haskell 对中缀运算符和前缀/非修复(这是一个词吗?)函数或变量进行了强烈的区分。
n
这样的简单函数参数,以及像 length
或 print
或 cos
这样的普通前缀函数。左关联解析规则适用于这些功能。对于您的示例,
+
运算符是唯一不在括号中的中缀,因此解析从分隔它每一侧的子表达式开始。
fibo n = ░ + ░
然后它才解析前缀应用程序,比如
fibo n = ░ + ░
┌───┴───┐ ┌───┴───┐
fibo(n-2) fibo(n-2)
内心的表达当然是一样的:
fibo n = ░ + ░
┌────┴────┐ ┌────┴────┐
fibo(░ - ░) fibo(░ - ░)
┌┴┐ ┌┴┐ ┌┴┐ ┌┴┐
n 1 n 2