2013-02-02 35 views
5

所以,讓我們直接點。地圖。 foldr函數組合 - 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) 
_________________________ 

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

+1

'foldr'類型錯誤,應該是'(a - > b - > b) - > b - > [a] - > b'。 –

回答

14

要回答這個問題,這是很好的回顧一下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) 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)。

+0

我在哪裏可以找到關於「地圖($ x)」成語的更多信息?我不明白。噢,謝謝你的回答,真的很有幫助:) – dehq

+1

運算符'$'由'f $ x = f x'定義,即它將左邊的函數應用於右邊的參數。這是絕對沒有必要的,但它有兩個方面的幫助:1. $'操作符具有最低的優先級並且關聯正確(不像函數應用程序具有最高優先級並且與左相關),所以您可以編寫'fa $ gb $ hc' fa(gb(hc))',2.你可以在一段中使用它,所以你可以寫'($ f)'而不是'\ a - > fa'。代碼'map($ x)'因此意味着與map(\ a - > x a)'相同。 –

1
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] 
2

要繼續你離開的地方,的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]