2013-02-02 43 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]