首页 > 解决方案 > 当我在另一个函数的应用程序中应用带有参数 n-1(无括号)的函数时,为什么会出现无限递归?

问题描述

在这里,我可以将参数传递给函数f7-1不带括号。

Prelude> f = (+1)
Prelude> f 7-1
7

1. 为什么下面是无限递归?

Prelude> addRec :: (Eq a, Num a) => a -> a; addRec 0 = 0; addRec n = n + addRec n-1;
Prelude> addRec 5

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

Prelude> addRec :: (Eq a, Num a) => a -> a; addRec 0 = 0; addRec n = n + addRec (n-1);

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

Prelude> addRec :: (Eq a, Num a) => a -> a; addRec 0 = 0; addRec n = n + (addRec $ n-1)

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

这是我的推理路线:

我们正在addRec n = n (...)有效地组合两个函数(不使用.组合运算符)。我们正在作曲(+)addRec。Haskell 在这个例子中是否理解我们有第三个功能(-)

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

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

标签: haskell

解决方案


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 $


推荐阅读