簡體   English   中英

無法理解haskell中的原始遞歸定義

[英]Can't get my head around primitive recursion definitions in haskell

我已經很好地了解了原始遞歸定義是什么,但是我似乎仍然無法理解它。

例如,我似乎無法向自己解釋如何執行以下操作(但我似乎能夠這樣做):

行使:

定義函數productIt :: [Int] -> Int ,它給出整數列表的乘積,並為空列表返回1; 為什么選擇此特定值作為空列表的結果?

我(當然)提出了解決方案:

productIt :: [Int] -> Int
productIt [] = 1
productIt (x:xs) = x * productIt xs

這對於練習中的問題非常有效。 然而,我似乎仍然難以繞過最后一行。

關於如何思考這一點的任何想法都將受到最高的贊賞。

在英語中,您可以將最后一行讀作:

數字列表的乘積是第一個數字乘以其余數字的乘積。 如果沒有數字,那么我們只說產品是1。

像這樣將它轉換為英語通常可以幫助我理解遞歸函數的工作原理和原因。 您也可以使用頭腦中的Haskell解釋器來評估它:

  productIt [2,3,4]
= 2 * (productIt [3,4])
= 2 * (3 * (productIt [4]))
= 2 * (3 * (4 * (productIt [])))
= 2 * (3 * (4 * (1)))
= 2 * (3 * (4))
= 2 * (12)
= 24

你使用1作為普通案例[]的原因是因為當你乘以它時它不會改變結果。

productIt (x:xs) = x * productIt xs

例如,假設您將其定義為:

productIt [] = 2                      -- line 1
productIt (x:xs) = x * productIt xs   -- line 2

然后考慮:

productIt [1] = productIt (1:[])
              = 1 * productIt []    -- by line 2
              = 1 * 2               -- by line 1
              = 2                   -- WRONG!!!

你正在尋找整數列表的乘積,對於[1],答案應該是1。

在我解釋最后一行代碼之前,讓我總結一下解決這類問題的過程。 有兩個關鍵問題:

  1. 什么是最簡單的案例?
  2. 我可以用下一個最簡單的解決方案來表達解決方案嗎?

好的,所以我們想編寫一個函數來計算列表中所有數字的乘積。

問題1:最簡單的情況是沒有任何數字。 如果這是我第一次遇到這個問題,對我來說可能不是很明顯,在這種情況下答案應該是什么,但讓我們暫時把它放在一邊。

問題2:如果我有一個列表[n0,n1,n2,... nk],並且我知道除了第一個數字之外的所有數字的產品(我們稱之為p),那么答案是第一個元素時間該產品,或n0 * p。

第一行代碼將處理瑣碎的案例:

productIt [] = 1

這表示空列表參數[]的函數productIt的值為1.(我在上面解釋了為什么答案必須為1.)這樣可以解決這個小問題。 現在我們需要在列表不為空的情況下定義productIt。 讓我們看看最后一行代碼:

productIt (x:xs) = ... something?

左側使用模式匹配。 模式(x:xs)將匹配具有一個或多個元素的列表。 當該表達式匹配時,它將x綁定到第一個元素,將xs綁定到列表的其余部分。 因此,我們不僅匹配模式,我們將x和xs定義為獎勵。 這就是使模式匹配在Haskell中非常強大的原因。

因此,如果列表的第一個元素是x,列表的其余部分(除第一個元素之外的所有元素)都是xs,那么答案是什么? 我們已經確定它是所有剩余元素(xs)的乘積的第一個元素(x)。 所以...

productIt (x:xs) = x * productIt xs

此外,yjerem為您提供了Haskell如何評估它的出色解釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM