地图.foldr函数组合 - Haskell

deh*_*ehq 5 haskell map fold function-composition

所以,让我们直截了当.

:t (map.foldr)
(map.foldr) :: (a1 -> a -> a) -> [a] -> [[a1] -> a]
Run Code Online (Sandbox Code Playgroud)

什么是[[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)
_________________________
Run Code Online (Sandbox Code Playgroud)

在这一点上会发生什么?谢谢!

Chr*_*lor 14

要回答这个问题,这是很好的回忆是什么foldrmap做.

两者中较为复杂的是foldr哪种类型

--              list to be folded
--                              v
foldr :: (a -> b -> b) -> b -> [a] -> b
--             ^          ^
--folding function        terminal value
Run Code Online (Sandbox Code Playgroud)

要折叠的列表实际上是一个conses链(:)和一个终端空列表:

1 : 2 : 3 : []
Run Code Online (Sandbox Code Playgroud)

动作foldr是分别用折叠函数和终值替换:[]构造函数:

foldr (+) 0 (1 : 2 : 3 : []) == 1 + 2 + 3 + 0
Run Code Online (Sandbox Code Playgroud)

map功能比较简单.考虑它的一种方法是获取函数和列表,并将函数应用于列表的每个参数:

map :: (a -> b) -> [a] -> [b]
--        ^         ^
-- function         list
Run Code Online (Sandbox Code Playgroud)

但是,您也可以将其视为一个函数,并将其提升为一个对列表起作用的函数:

map :: (a -> b) -> ( [a] -> [b] )
--        ^              ^
-- function              function on lists
Run Code Online (Sandbox Code Playgroud)

组成这两个函数意味着什么map . foldr?请注意,这只是一个接一个地应用这些功能 - 特别是

(map . foldr) f == map (foldr f)
Run Code Online (Sandbox Code Playgroud)

既然你foldr先申请,你必须将它应用于一个函数f :: a -> b -> b,然后你得到另一个函数:

foldr f :: b -> [a] -> b
--         ^     ^
--terminal val   list to be folded
Run Code Online (Sandbox Code Playgroud)

现在你申请map,它提升了对列表采取行动的功能:

map (foldr f) :: [b] -> [[a] -> b]
--                ^          ^
--list of terminal vals      functions that fold lists
Run Code Online (Sandbox Code Playgroud)

这种类型看起来很奇怪,但它是有效的.现在,不是单个终端值,而是给它一个终端值列表,然后返回折叠函数列表 - 每个终端值对应一个.


为了更清楚,我们可以查看(+)具有类型的特定函数

(+) :: Num a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

如果我们将其替换为上面的等式,我们得到

(map . foldr) (+) :: Num a => [a] -> [[a] -> a]
--                             ^          ^
--         list of terminal vals          functions that fold lists
Run Code Online (Sandbox Code Playgroud)

如果我们现在将它应用于列表,[0, 1, 2]我们将获得三个函数的列表:

(map . foldr) (+) [0,1,2] :: Num a => [[a] -> a]
Run Code Online (Sandbox Code Playgroud)

我们可以使用这个map ($x)习惯用法将列表中的每个函数应用于特定的参数.它必须是一个数字列表,我会选择[3,4,5].仔细观察:

> map ($[3,4,5]) ((map.foldr) (+) [0,1,2])
[12, 13, 14]
Run Code Online (Sandbox Code Playgroud)

[3,4,5]使用(+)折叠功能将列表折叠三次,每次使用不同的终端值:

3 + 4 + 5 + 0 == 12
3 + 4 + 5 + 1 == 13
3 + 4 + 5 + 2 == 14
Run Code Online (Sandbox Code Playgroud)

当终值是0,我们只需得到值的总和:3 + 4 + 5 == 12.当终值时,1我们得到的值多于值(13)的总和,当终值为时,2我们得到的值比值的总和(14)多两倍.