要回答這個問題,這是很好的回顧一下foldr
和map
呢。
越複雜兩個是foldr
,其類型爲
-- list to be folded
-- v
foldr :: (a -> b -> b) -> b -> [a] -> b
-- ^ ^
--folding function terminal value
被摺疊的列表是真的conses之外(:)
和終端空列表的鏈:
1 : 2 : 3 : []
動作foldr
的作用是分別用摺疊函數和終值替換:
和[]
構造函數:
foldr (+) 0 (1 : 2 : 3 : []) == 1 + 2 + 3 + 0
的map
功能比較簡單。它的思想的一種方式是爲取一個函數和一個列表,並應用功能列表中的每一個論點:
map :: (a -> b) -> [a] -> [b]
-- ^ ^
-- function list
但是,你也可以把它當作利用函數,並將其提升到是作用於列表的函數:
map :: (a -> b) -> ([a] -> [b])
-- ^ ^
-- function function on lists
是什麼意思撰寫這兩個功能,map . foldr
?請注意,這只是應用功能一前一後 - 特別是
(map . foldr) f == map (foldr f)
既然你申請foldr
首先,你必須把它應用到一個功能f :: a -> b -> b
,而你回來的另一個功能:
foldr f :: b -> [a] -> b
-- ^ ^
--terminal val list to be folded
現在你申請map
,又帶動作用於列表功能:
map (foldr f) :: [b] -> [[a] -> b]
-- ^ ^
--list of terminal vals functions that fold lists
這種看起來很奇怪,BU這是有效的。現在不用一個終端值,而是給它一個終端值列表,並且您會得到一個摺疊功能列表 - 您爲每個終端值提供一個摺疊功能。
使其更清晰,我們可以看一個特定的功能,(+)
,其類型爲
(+) :: Num a => a -> a -> a
如果我們替代品上面的等式,我們得到
(map . foldr) (+) :: Num a => [a] -> [[a] -> a]
-- ^ ^
-- list of terminal vals functions that fold lists
如果我們現在將其應用到名單[0, 1, 2]
我們得到三個功能的列表:
(map . foldr) (+) [0,1,2] :: Num a => [[a] -> a]
我們可以使用map ($x)
成語將列表中的每個函數應用於特定參數。它必須是一個數字列表,我會選擇[3,4,5]
。仔細觀察:
> map ($[3,4,5]) ((map.foldr) (+) [0,1,2])
[12, 13, 14]
[3,4,5]
摺疊使用(+)
作爲摺疊功能三倍的名單,並用不同的終值每次:
3 + 4 + 5 + 0 == 12
3 + 4 + 5 + 1 == 13
3 + 4 + 5 + 2 == 14
當終端值爲0
,我們只是得到值的總和:3 + 4 + 5 == 12
。當終端值爲1
時,我們得到比值(13
)的總和多一個,並且當終端值爲2
時,我們得到兩個比值的總和(14
)。
'foldr'類型錯誤,應該是'(a - > b - > b) - > b - > [a] - > b'。 –