[英]Haskell Recursive 'sum' Function
我發現很難理解以下遞歸函數的機制:
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”?
任何幫助深表感謝!
您可以通過逐步簡化來了解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]
。
這與其他語言中的遞歸沒有什么不同。 當首先sums [0..4]
(不需要括號)時, x==0
, y==1
, ys == [2..4]
。 因此,返回值是一個從0
創建的新列表,該列表與sums [1..4]
。
用嚴格的語言來說,遞歸調用將在最終創建新列表之前完成。 由於Haskell是惰性的,因此將返回一個列表,該列表以0開頭,並以一個對sums [1..4]
的承諾繼續。 除非有人實際嘗試訪問列表的末尾,否則不會真正評估遞歸調用。
您可能會注意到
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:[]
有兩個方程式定義函數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]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.