要回答这个问题,这是很好的回顾一下foldr
和map
呢。
越复杂两个是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
)。
'foldr'类型错误,应该是'(a - > b - > b) - > b - > [a] - > b'。 –