当我在另一个函数的应用程序内部应用参数为n-1(无括号)的函数时,为什么会有无限递归?

evi*_*ing 2 haskell

在这里,我可以传递f参数的功能7-1,不带括号。

Prelude> f = (+1)
Prelude> f 7-1
7
Run Code Online (Sandbox Code Playgroud)

1. 为什么以下无限递归?

Prelude> addRec :: (Eq a, Num a) => a -> a; addRec 0 = 0; addRec n = n + addRec n-1;
Prelude> addRec 5
Run Code Online (Sandbox Code Playgroud)

2. 我可以通过添加括号来解决它n-1

Prelude> addRec :: (Eq a, Num a) => a -> a; addRec 0 = 0; addRec n = n + addRec (n-1);
Run Code Online (Sandbox Code Playgroud)

3. 或者$在整个addRec递归项上使用带括号的运算符:

Prelude> addRec :: (Eq a, Num a) => a -> a; addRec 0 = 0; addRec n = n + (addRec $ n-1)
Run Code Online (Sandbox Code Playgroud)

我想确切地了解每个表达式如何工作或不工作。

这是我的推理路线:

addRec n = n (...)有效地组成两个函数(不使用.composition运算符)。我们正在构图(+)addRec。在此示例中,Haskell是否了解我们具有第三个功能(-)

我们正在使用函数应用程序(据我所知,函数应用程序后面的空格表示运算符)来实现这种组合。

函数应用程序是左关联的,所以我的第一个问题是:addRec n = n + addRec n-1添加与默认左关联性相对应的括号时会是什么样?

Fyo*_*kin 12

f 7-1 并不代表您的意思。

在Haskell中,功能应用程序具有最高优先级。这意味着f 7-1始终被解释为(f 7) - 1。负号周围没有空格是无关紧要的,只有通过巧合,您才能得到正确的答案:f 7 = (+ 1) 7 = 8,然后8 - 1 = 7。如果您的函数定义为,则不会发生这种情况f = (* 2)

同样,addRec n-1被解释为(addRec n) - 1,因此每次都调用addRec相同的参数,从而n产生无限递归。

已知的两种修复方法:parens或operator $