我发现很难理解以下递归函数的机制:
sums (x:y:ys) = x:sums(x + y : ys)
sums xs = xs
sums ([0..4])
Output:
[0, 1, 3, 6, 10]
这一行究竟发生了什么?:
x:sums(x + y : ys)
我想说在程序可以将'x'附加到列表之前,必须首先执行函数sum(x + y:ys)。但在这种情况下,'x'只会在递归循环结束时附加到列表中一次 - 这不会导致给定的输出......那么我逻辑中的缺陷在哪里?
我的后续问题:我应该如何以合乎逻辑的方式看待/处理递归函数,这会(希望)将我引向'aha-erlebnis'?
非常感谢任何帮助!
答案 0 :(得分:9)
您可以通过逐步减少来理解Haskell代码。也许以下示例缩减序列可以帮助您实现这一目标。
(一个Haskell实现实际上做了一些与这种减少步骤相关的事情,但可能是以不同的顺序。但是你得到了相同的最终结果。)
在此示例中,您从:
开始sums [0..4]
稍微扩展[0..4]
符号:
sums (0 : 1 : [2..4])
现在我们看到sums
的第一个等式与x = 0
,y = 1
和ys = [2..4]
匹配。所以我们得到:
0 : sums (0 + 1 : [2..4])
我们可以计算0 + 1
:
0 : sums (1 : [2..4])
稍稍展开[2..4]
:
0 : sums (1 : 2 : [3..4])
现在我们看到sums
的第一个等式再次匹配,这次是x = 1
,y = 2
和ys = [3..4]
。所以我们得到:
0 : 1 : sums (1 + 2 : [3..4])
我们可以计算1 + 2
:
0 : 1 : sums (3 : [3..4])
稍稍展开[3..4]
:
0 : 1 : sums (3 : 3 : [4..4])
现在我们看到sums
的第一个等式再次匹配,这次是x = 3
,y = 3
和ys = [4..4]
。所以我们得到:
0 : 1 : 3 : sums (3 + 3 : [4..4])
我们可以计算3 + 3
:
0 : 1 : 3 : sums (6 : [4..4])
展开[4..4]
:
0 : 1 : 3 : sums (6 : 4 : [])
现在我们看到sums
的第一个等式再次匹配,这次是x = 6
,y = 4
和ys = []
。所以我们得到:
0 : 1 : 3 : 6 : sums (6 + 4 : [])
我们可以计算6 + 4
:
0 : 1 : 3 : 6 : sums (10 : [])
这一次,sums
的第一个等式不匹配。但第二个等式匹配。所以我们得到:
0 : 1 : 3 : 6 : 10 : []
这是观察到的输出[0, 1, 3, 6, 10]
。
答案 1 :(得分:3)
这与任何其他语言中的递归没有什么不同。首次调用_.chunk
(不需要括号)时,sums [0..4]
,x==0
和y==1
。因此,返回值是从ys == [2..4]
和0
创建的新列表。
在严格的语言中,递归调用将在最终创建新列表之前完成。由于Haskell是惰性的,因此返回一个以0开头并继续使用 promise 来评估sums [1..4]
的列表。在实际尝试访问列表尾部之前,实际上不会评估递归调用。
答案 2 :(得分:1)
您可能会注意到
sums (x:y:ys) = x:sums(x + y : ys)
相当于
sums (x:y:z:ys) = x:x+y:sums(x+y+z : ys)
sums (x:y:ys) = x:sums(x + y : ys)
和(超过2项)也相当于
sums (x:y:z: w: ys) = x:x+y:x+y+z:sums(x+y+z +w: ys)
sums (x:y:z:ys) = x:x+y:sums(x+y+z : ys)
sums (x:y:ys) = x:sums(x + y : ys)
所以通过归纳你有那个
sums(1:2:3:4 :[])
等于
1 : 1 + 2 : 1 + 2 + 3 : 1 + 2 + 3 + 4 : []
基于以上内容,您还可以使用
预测fact(x:y:ys) = x: fact(x * y : ys)
fact(xs) = xs
然后
fact([1..4])
是
1:1*2:1*2*3:1*2*3*4:[]
答案 3 :(得分:0)
有两个方程定义函数sums
。使用匹配参数的第一个等式或其他合适的等式(如1 + 2 = 3)继续重写涉及sums
的表达式。
sums [0..4] =
-- by syntactic sugar
sums (0:1:2:3:4:[]) =
-- by eq. 1, x=0,y=1,ys=2:3:4:[]
0 : sums ((0+1) : 2 : 3:4:[]) =
-- by addition
0 : sums (1 : 2 : 3:4:[]) =
-- by eq. 1, x=1, y=2, ys=3:4:[]
0 : 1 : sums ((1+2) : 3 : 4:[]) =
-- by addition
0 : 1 : sums (3 : 3 : 4:[]) =
-- by eq. 1, x=3, y=3, ys=4:[]
0 : 1 : 3 : sums ((3+3) : 4 : []) =
-- by addition
0 : 1 : 3 : sums (6 : 4 : []) =
-- by eq. 1, x=6, y=4, ys=[]
0 : 1 : 3 : 6 : sums ((6+4):[]) =
-- by addition
0 : 1 : 3 : 6 : sums (10:[]) =
-- by eq 2,xs=(10:[])
0 : 1 : 3 : 6 : 10 : [] =
-- by syntactic sugar
[0,1,3,6,10]