Haskell - 操作的优先级

问题描述 投票:0回答:2

我试图弄清楚 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

不被接受。

haskell functional-programming operator-precedence
2个回答
2
投票

对于最后一个表达式,这将被解释为:

(((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
一样。


0
投票

Haskell 对中缀运算符和前缀/非修复(这是一个词吗?)函数或变量进行了强烈的区分。

  • 任何仅包含字母、下划线和/或非前导数字且以小写字母或下划线开头的内容都是 variable。这包括像
    n
    这样的简单函数参数,以及像
    length
    print
    cos
    这样的普通前缀函数。左关联解析规则适用于这些功能。
  • 任何包含非字母/数字代码点的东西都是中缀运算符。它们的解析完全不同,即 always bind 弱于函数应用,它们在运算符的两边绑定东西,并且它们有自己的优先级层次结构。

对于您的示例,

+
运算符是唯一不在括号中的中缀,因此解析从分隔它每一侧的子表达式开始。

fibo n = ░ + ░

然后它才解析前缀应用程序,比如

fibo n =    ░    +     ░
        ┌───┴───┐  ┌───┴───┐
        fibo(n-2)  fibo(n-2)

内心的表达当然是一样的:

fibo n =     ░     +      ░
        ┌────┴────┐  ┌────┴────┐
        fibo(░ - ░)  fibo(░ - ░)
            ┌┴┐ ┌┴┐      ┌┴┐ ┌┴┐
             n   1        n   2
© www.soinside.com 2019 - 2024. All rights reserved.