Haskell 当我在另一个函数的应用程序中应用一个参数为n-1(没有括号)的函数时,为什么会出现无限递归?
这里我可以将参数Haskell 当我在另一个函数的应用程序中应用一个参数为n-1(没有括号)的函数时,为什么会出现无限递归?,haskell,Haskell,这里我可以将参数7-1传递给函数f,不带括号 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) =>
7-1
传递给函数f
,不带括号
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)
我想确切地了解每个表达式是如何工作的或不工作的
以下是我的推理:
在addrecn=n(…)
中,我们有效地组合了两个函数(不使用
组合运算符)。我们正在编写(+)
和addRec
。本例中的Haskell是否理解我们有第三个函数(-)
我们使用函数应用程序(据我所知,它是由函数后面的空格表示的运算符)来实现这种组合
函数应用程序是左关联的,所以我的第一个问题是:当我们添加与默认左关联性对应的括号时,
addRec n=n+addRec n-1
是什么样子 f7-1
并不是你认为它的意思
在Haskell中,函数应用程序具有最高优先级。这意味着f7-1
始终被解释为(f7)-1
。减号周围没有空格是不相关的,只是碰巧你得到了正确的答案:f7=(+1)7=8
,然后8-1=7
。如果将函数定义为f=(*2)
,则不会发生这种情况
类似地,addRec n-1
被解释为(addRec n)-1
,因此每次都使用相同的参数n
调用addRec
,从而产生无限递归
修复它的两种方法,您已经知道:parens或operator
$
函数应用程序优先于所有其他运算符addRec n-1
被解析为(addRec n)-1
。你只能用显式括号或$
操作符来解决这个问题。我不同意投票结果。这不是一个印刷错误,而是(非常常见的)对Haskell运算符优先规则的误解。这可能不是一个印刷错误,但我认为它不需要另一个解释基本优先规则的答案。我认为meta中有一个讨论指出,可以通过简单评论解决的琐碎问题可以包含在“不再复制”下。@chepner我不同意这是一个“琐碎”问题,因为如果是这样,可能会有重复的问题。此外,对一个人来说微不足道的事情对另一个人来说未必微不足道。我也不同意基于一些关于元的讨论,用错误的理由来结束一个问题。如果你想正式提出一个理由来结束一个问题,因为它是琐碎的,那没关系,但在那之前,对一个问题投否决票(因为“没有用”)比因为一个虚假的理由投票结束更合适。我认为这是如此基本,以至于没有一个重复,但有许多问题归结为同一个基本问题:不理解优先权。也许应该有一个单一的、规范的问题来处理这个问题,但我不确定如何最好地构建它。