我理解foldl,foldr的定义,但我对它们定义的函数有问题。
例如,带有foldr的地图:
map f [] = []
map f l = foldr (\x xs -> f x : xs) [] l
我不理解(\x xs -> f x : xs)
。它是map函数,foldr采用哪种?但不应该是(\x xs -> f x : f xs)
,因为map f (x:xs) = f x : map f xs
?
foldl示例:
concat (x:xs) = x ++ concat xs
concat' xs = foldl (++) [] xs
concat'' xs = foldl (\ys y -> ys ++ y) [] xs
我当然理解(++)
,但(\ys y -> ys ++ y)
背后的逻辑是什么?是ys = []
还是y = xs
?
因此,该函数将[]
作为ys
,y
是xs
的第一个元素,并将[]
与y
结合在一起?
具体例子:
concat'' [1,2,3] = foldl (\ys y -> ys ++ y) [] [1,2,3]
=> foldl (\ys y -> ys ++ y) ((\ys y -> ys ++ y) [] [1]) [2,3]
=> foldl (\ys y -> ys ++ y) [1] [2,3]
=> foldl (\ys y -> ys ++ y) ((\ys y -> ys ++ y) [1] [2]) [3]
=> foldl (\ys y -> ys ++ y) [1,2] [3]
=> foldl (\ys y -> ys ++ y) ((\ys y -> ys ++ y) [1,2] [3]) []
=> foldl (\ys y -> ys ++ y) [1,2,3] []
=> [1,2,3]
另一件事:concat
只需要1个列表xs
,所以如果我要连接2个列表?
concat (x:xs) ys = x ++ concat xs ys
concat [1,2,3] [4,5,6] with foldl?
反向:
reverse (x:xs) = reverse xs ++ [x]
reverse' l = foldl (\xs x -> [x] : xs) [] l
reverse'' l = foldr (\x xs -> xs ++ [x]) [] l
折叠器直观清晰(带有上面的问题),但是在foldl (\xs x -> [x] : xs)
中反向顺序的背后是什么?这foldl (\x xs -> xs ++ [x]) [] l
会出错,不是吗?
非常感谢!
答案 0 :(得分:2)
代码
foldr (\x xs -> ...) end list
大致可以读取如下
list
end
x
成为手头的元素xs
成为列表的其余部分,经过处理 ...
操作强调部分至关重要。 xs
不列表的其余部分,但是“递归调用”的结果。
事实上,xs
是一个坏名声。在一般情况下,它甚至不是一个列表!例如。一个人永远不会写(愚蠢的例子)
foldr (\x xs -> x + xs) 0 [1..100] -- sum 1..100
但更喜欢像
这样的东西foldr (\x partialSum -> x + partialSum) 0 [1..100] -- sum 1..100
(实际上,人们不会使用foldr
求和,但让我们把它放在一边。)
所以,请按照以下方式阅读:
map f l = foldr (\x mappedTail -> f x : mappedTail) [] l