haskell - 当我在另一个函数的应用程序中应用带有参数 n-1(无括号)的函数时,为什么会出现无限递归?
问题描述
在这里,我可以将参数传递给函数f
,7-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
当我们添加与默认左关联对应的括号时会是什么样子?
解决方案
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 $
。
推荐阅读
- css - CSS:框列根据里面的内容自动增加高度
- docker - 如何将 gpus 添加到正在运行的 Docker 容器中?
- python - Mininet_wifi iperf 与一台服务器和多个客户端
- c++ - 即使在共享库中定义了函数,链接器错误未定义引用
- shell - 当命令在本地(/bin/sh -c CMD)与远程(ssh node1 /bin/sh -c CMD)运行时,shell(sh 或 csh)在处理参数方面的行为是否不同?
- javascript - VueJs 路由器:App.vue 组件显示在每个页面上
- silverstripe - Silverstripe - 重复/可重复使用的分组字段
- html - 两列的 CSS 网格布局
- python - 绘制具有时间间隔的 Panda 数据框的箱线图
- node.js - nodejs mongodb在发布新行时存储函数中的变量