繁体   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