简体   繁体   English

使用foldl foldr定义函数

[英]Define functions with foldl foldr

I understand the definitions of foldl, foldr, but I have problems with functions defined by them. 我了解foldl,foldr的定义,但是它们定义的功能存在问题。

For example map with foldr: 例如,带有文件夹的地图:

map f []       = []
map f l   = foldr (\x xs -> f x : xs) [] l

I don't understand the (\\x xs -> fx : xs) . 我不明白(\\x xs -> fx : xs) It is the map function, which foldr takes? 是地图功能,哪个文件夹需要? But shouldn't it be (\\x xs -> fx : f xs) , because map f (x:xs) = fx : map f xs ? 但是不应该是(\\x xs -> fx : f xs) ,因为map f (x:xs) = fx : map f xs吗?

Example with foldl: foldl的示例:

concat (x:xs) = x ++ concat xs

concat' xs = foldl (++) [] xs
concat'' xs = foldl (\ys y -> ys ++ y) [] xs

Of course I understand (++) , but what's the logic behind (\\ys y -> ys ++ y) ? 我当然理解(++) ,但是(\\ys y -> ys ++ y)背后的逻辑是什么? Is it ys = [] and y = xs ? ys = []y = xs吗? So the function takes [] as ys and y is the first element of xs and concates the [] with the y ? 因此,该函数将[]设为ys并且yxs的第一个元素,并将[]包含为y Concrete example: 具体示例:

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]

Another thing: concat only takes 1 list xs , so if I want to concat 2 lists? 另一件事: concat只接受1个列表xs ,所以如果我要concat 2个列表?

concat (x:xs) ys = x ++ concat xs ys
concat [1,2,3] [4,5,6] with foldl?

Reverse: 相反:

reverse (x:xs) = reverse xs ++ [x]

reverse'  l = foldl (\xs x -> [x] : xs) [] l
reverse'' l = foldr (\x xs -> xs ++ [x]) [] l

The foldr is intuitive clear (with the questions from above), but what's behind the reverse order in foldl (\\xs x -> [x] : xs) ? 文件夹清晰直观(上面有问题),但是在文件夹(\\xs x -> [x] : xs)相反的顺序背后是什么? This foldl (\\x xs -> xs ++ [x]) [] l would be wrong, wouldn't it? 这个文件foldl (\\x xs -> xs ++ [x]) [] l是错误的,不是吗?

Thanks a lot! 非常感谢!

The code 编码

foldr (\x xs -> ...) end list

could be read, roughly, as follows 可以大致如下读取

  • scan the whole list 扫描整个list
  • if it's empty, just return end end 如果为空,则返回end end
  • otherwise: 除此以外:
    • let x be the element at hand x成为手头的元素
    • let xs be the rest of the list, after having been processed 经过处理后,xs为列表的其余部分
    • apply the ... operation 应用...操作

The emphasized part is crucial. 强调的部分至关重要。 xs is not the rest of the list, but the result of the "recursive call" on it. xs 不是列表的其余部分,而是列表上“递归调用”的结果。

Indeed, xs is a bad name for that. 的确, xs是个坏名字。 In thee general case, it's not even a list! 在一般情况下,它甚至都不是列表! Eg one would never write (silly example) 例如,一个人永远不会写(愚蠢的例子)

foldr (\x xs -> x + xs) 0 [1..100]  -- sum 1..100

but rather prefer something like 但宁愿喜欢这样的东西

foldr (\x partialSum -> x + partialSum) 0 [1..100]  -- sum 1..100

(Actually, one would not sum using foldr , but let's leave that aside.) (实际上,不会使用foldr求和,但我们将其放在一边。)

So, just read it like this: 因此,只需像这样阅读:

map f l   = foldr (\x mappedTail -> f x : mappedTail) [] l

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM