Foldr 和 Foldl 进一步解释和示例
我查看了不同的折叠和一般折叠 以及其他一些内容,他们解释得相当好。
我仍然不知道 lambda 在这种情况下如何工作。
foldr (\y ys -> ys ++ [y]) [] [1,2,3]
有人可以逐步完成该过程并尝试向我解释吗?
还有 foldl
是如何工作的?
I've looked at different folds and folding in general as well as a few others and they explain it fairly well.
I'm still having trouble on how a lambda would work in this case.
foldr (\y ys -> ys ++ [y]) [] [1,2,3]
Could someone go through that step-by-step and try to explain that to me?
And also how would foldl
work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
foldr 是一件简单的事情:
它需要一个类似于 (:) 的函数
和一个类似于空列表 [] 的值,
并替换某个列表中的每个 : 和 []。
它看起来像这样:
您也可以将foldr想象为某种状态机评估器:
f是转换,
e是开始状态。
foldr (foldRIGHT) 在输入列表上运行带有转换 f 和起始状态 e 的状态机,从右端开始。想象一下中缀表示法中的 pacman 来自右方。
Foldl (foldLEFT) 从左开始执行相同的操作,但以中缀表示法编写的转换函数从右获取其输入参数。因此机器从左端开始消耗列表。 Pacman 从左开始使用张开的嘴向右消费列表,因为嘴是 (b->a->b) 而不是 (a->b->b)。
为了清楚地说明这一点,请将函数
(-)
想象为转换:您可能希望在列表可以无限且评估应该惰性的情况下使用foldr:
并且您可能希望使用当您使用整个列表来生成其输出时,foldl 的严格版本是 Foldl'。它可能会表现得更好,并且可能会防止您因极长的列表与惰性求值相结合而出现堆栈溢出或内存不足异常(取决于编译器):
第一个 - 一步一步 - 创建列表的一个条目,对其进行评估并使用它。
第二个首先创建一个非常长的公式,使用 ((...((0+1)+2)+3)+...) 浪费内存,然后对所有公式进行求值。
第三个与第二个类似,但公式不同。
foldr is an easy thing:
It takes a function which is somehow similar to (:),
and a value which is similar to the empty list [],
and replaces each : and [] in some list.
It looks like this:
You can imagine foldr as some state-machine-evaluator, too:
f is the transition,
and e is the start state.
foldr (foldRIGHT) runs the state-machine with the transition f and the start state e over the list of inputs, starting at the right end. Imagine f in infix notation as the pacman coming from-RIGHT.
foldl (foldLEFT) does the same from-LEFT, but the transition function, written in infix notation, takes its input argument from right. So the machine consumes the list starting at the left end. Pacman consumes the list from-LEFT with an open mouth to the right, because of the mouth (b->a->b) instead of (a->b->b).
To make this clear, imagine the function
(-)
as transition:You probably want to use foldr in situations where the list can be infinite, and where the evaluation should be lazy:
And you probably want to use the strict version of foldl, which is foldl', when you consume the whole list to produce its output. It might perform better and might prevent you from having stack-overflow or out-of-memory exceptions (depending on compiler) due to extreme long lists in combination with lazy evaluation:
The first one –step by step– creates one entry of the list, evaluates it, and consumes it.
The second one creates a very long formula first, wasting memory with ((...((0+1)+2)+3)+...), and evaluates all of it afterwards.
The third one is like the second, but with the other formula.
使用
并
解压:
Using
And
Let's unpack:
foldr
的定义是:因此,这是示例的逐步简化:
The definition of
foldr
is:So here's a step by step reduction of your example:
中缀表示法在这里可能会更清楚。
让我们从定义开始:
为了简洁起见,让我们写成
g
而不是(\y ys -> ys ++ [y])
。以下几行是等效的:Infix notation will probably be clearer here.
Let's start with the definition:
For the sake of brevity, let's write
g
instead of(\y ys -> ys ++ [y])
. The following lines are equivalent:我首先记住这一点的方法是通过使用关联敏感减法操作:
然后,
foldl
从最左边或第一个元素开始列表的元素,而foldr
从列表的最右边或最后一个元素开始。上面这一点并不明显,因为列表只有一个元素。我的助记符是这样的:
left
或right
描述了两件事:-
) 符号的位置My way of remembering this firstly, is through the use of an associative sensitive subtraction operation:
Then secondly ,
foldl
starts at the leftmost or first element of the list whereasfoldr
starts at the rightmost or last element of the list. It is not obvious above since the list has only one element.My mnemonic is this: The
left
orright
describes two things:-
) symbol我倾向于通过运动来记住事物,所以我想象并想象飞来飞去的价值观。这是我对foldl 和foldr 的内部表示。
下图做了一些事情:
便于记忆的是,我记得foldl的参数按字母顺序排列(
\ac ->
),foldr的参数按相反的字母顺序排列(\ca ->
)代码>)。l
表示从左侧获取,r
表示从右侧获取。I tend to remember things with movement, so I imagine and visualize values flying around. This is my internal representation of foldl and foldr.
The diagram below does a few things:
Mnemonically, I remember the arguments of foldl as being in alphabetical order (
\a c ->
), and the arguments of foldr to be in reverse alphabetical order (\c a ->
). Thel
means take from the left, ther
means take from the right.