[英]Need help understanding what this Haskell function does
不確定這到底是做什么的,或者在函數中輸入什么以在輸出中找到模式
f0 f id [] = id
f0 f id (x:xs) = f x (f0 f id xs)
f
和id
在每次遞歸調用中都保持不變,所以讓我們稍微簡化一下:
f0 [] = id
f0 (x:xs) = f x (f0 xs)
這意味着f0 xs
可以擴展為:
f x1 (f x2 (f x3 id))
哪種看起來像foldr
。 那是因為它是foldr
。
Prelude> foldr (+) 0 [1, 2, 3]
6
Prelude> f0 (+) 0 [1, 2, 3]
6
好的。 讓我們來看看吧。 這是一個具有基本情況和遞歸步驟的遞歸函數。 它被命名為f0
並具有三個參數, f
、 id
(它與 Prelude 中的函數具有相同的名稱,令人困惑)和(x:xs)
。 不幸的是,它沒有類型簽名,但我們已經可以看出第三個是某種列表。 所以它的簽名將類似於f0 :: a -> b -> [c] -> d
基本情況很簡單:如果第三個參數是一個空列表,則函數返回id
,因此它具有函數返回的類型。 所以這兩種類型是相同的,我們可以將類型簽名細化為f0 :: a -> b -> [c] -> b
。
遞歸情況僅在列表(x:xs)
不為空時才被調用。 它調用f
,因此它必須是一個有兩個參數的函數,其中x
(列表的頭部)作為f
的第一個參數,對f0
的調用作為第二個參數。 由於f
的返回值是f0
的有效返回值,因此它們必須具有相同的返回類型。 因此,此時我們可以推斷,如果b
是f0
的返回類型,而[a]
是第三個參數的類型,則該函數的簽名必須是:
f0 :: (a -> b -> b) -> b -> [a] -> b
現在,讓我們仔細看看遞歸步驟中f
的第二個參數。 它調用f0 f id xs
,這是完全相同的調用,但是在列表的尾部。 (因此,列表每一步都縮短一個元素,直到它為空並且我們達到基本情況,因此算法必須終止。)因此, f0 (+) 0.0 [1,2,3]
擴展為1 + (2 + (3 + 0.0) )
。 這是 Prelude 的一個功能; 你能說出哪個嗎?
編輯:另一個答案破壞了它,但我會注意到名稱也是提示。 f0
和f
是函數, id
是標識元素的縮寫(因為預期模型是將它添加到列表的最后一個元素並返回相同的元素,添加 3 + 0.0 的方式為您提供浮點數3.0),而x:xs是在遞歸函數中引用列表參數的傳統方式。
為了破譯代碼,我有時發現利用Data.SimpleReflect
並運行一些測試很有用。
> import Debug.SimpleReflect
> let f0 f id [] = id ; f0 f id (x:xs) = f x (f0 f id xs)
> f0 f a [b,c,d,e]
f b (f c (f d (f e a)))
看起來很眼熟……是foldr
嗎?
> foldr f a [b,c,d,e]
f b (f c (f d (f e a)))
好的,是的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.