使用foldl foldr定义函数

时间:2016-07-03 10:55:49

标签: haskell dictionary functional-programming fold

我理解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? 因此,该函数将[]作为ysyxs的第一个元素,并将[]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会出错,不是吗?

非常感谢!

1 个答案:

答案 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