簡體   English   中英

地圖。 foldr函數組合 - Haskell

[英]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)
_________________________

在這一點上會發生什么? 謝謝!

要回答這個問題,最好回想一下foldrmap作用。

兩者中較為復雜的是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.

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