[英]map . foldr function composition - Haskell
所以,讓我們直截了當。
:t (map.foldr)
(map.foldr) :: (a1 -> a -> a) -> [a] -> [[a1] -> a]
什么是[[a1] - > a]? 我真的想要理解這個構圖,所以我這樣做:
-- map.foldr
map.foldr :: (a1 -> a -> a) -> [a] -> [[a1] -> a]
map :: (a1 -> b1) -> [a1] -> [b1]
(.) :: (y -> w) -> (x -> y) -> x -> w
foldr :: (a -> b -> b) -> b -> [a] -> b
y = (a1 -> b1) w = ([a1] -> [b1])
x = (a -> b -> b) y = (b -> [a] -> b)
y = (a1 -> b1)
y = (b -> [a] -> b)
_________________________
在這一點上會發生什么? 謝謝!
要回答這個問題,最好回想一下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
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
這種類型看起來很奇怪,但它是有效的。 現在,不是單個終端值,而是給它一個終端值列表,然后返回折疊函數列表 - 每個終端值對應一個。
為了更清楚,我們可以查看具有類型的特定函數(+)
(+) :: 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)
idiom將列表中的每個函數應用於特定參數。 它必須是一個數字列表,我將選擇[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
)多兩個。
要從中斷的地方繼續, y
的兩個定義必須相等:
y = (a1 -> b1) = (b -> [a] -> b)
= (b -> ([a] -> b))
所以我們可以得出結論:
a1 = b
b1 = [a] -> b
函數組合已經提供了兩個函數參數,因此結果類型只是:
x -> w
但我們知道:
x = a -> b -> b
w = [a1] -> [b1] = [b] -> [[a] -> b]
所以,結果類型是:
(x -> w) = ((a -> b -> b) -> ([b] -> [[a] -> b]))
= (a -> b -> b) -> [b] -> [[a] -> b]
這與以下內容一致:
(a1 -> a -> a) -> [a] -> [[a1] -> a]
map.foldr :: (a1 -> a -> a) -> [a] -> [[a1] -> a]
map :: (a1 -> b1) -> [a1] -> [b1]
(.) :: (y -> w) -> (x -> y) -> x -> w
foldr :: (a -> b -> b) -> b -> [a] -> b
-- if you substitute: x = (a -> b -> b) y = (b -> [a] -> b)
-- then you get for map :: (b -> ([a] -> b)) -> [b] -> [[a] -> b]
-- so if composition operator applied:
map . foldr :: (a -> b -> b) -> [b] -> [[a] -> b]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.