foldl / foldr查询
我是Haskell的初学者,甚至在阅读了foldr / foldl的几个解释之后,我无法理解为什么我会在下面得到不同的结果。 什么是解释?
Prelude> foldl (_ -> (+1)) 0 [1,2,3]
4
Prelude> foldr (_ -> (+1)) 0 [1,2,3]
3
谢谢!
在foldl
情况下,lambda传递的是累加器作为第一个参数,而列表元素作为第二个参数。 在foldr
情况下,lambda被作为第一个参数传递给list元素,第二个作为累加器。
你的lambda忽略了第一个参数,并在第二个参数中加1,所以在foldl
情况下,你要为最后一个元素加1,在foldr
情况下,你要计算列表中元素的数量。
这是因为参数的顺序在foldl
翻转。 比较他们的类型签名:
foldl :: (a -> b -> a) -> a -> [b] -> a
foldr :: (a -> b -> b) -> b -> [a] -> b
所以你看到,在你的代码中使用foldl
,你会重复增加累加器,忽略列表。 但是在使用foldr
的代码中,您甚至不会触摸累加器,只是增加列表的元素。 最后一个元素是3
,结果是3 + 1 = 4
。
你可以看到你的错误更容易,如果你使用一个字符列表,也就是字符串:
ghci> foldr (_ -> (+1)) 0 ['a','b','c'] 3 ghci> foldl (_ -> (+1)) 0 ['a','b','c'] :1:20: No instance for (Num Char) arising from the literal `0' Possible fix: add an instance declaration for (Num Char) In the second argument of `foldl', namely `0' In the expression: foldl ( _ -> (+ 1)) 0 ['a', 'b', 'c'] In an equation for `it': it = foldl ( _ -> (+ 1)) 0 ['a', 'b', 'c'] ghci>
不同之处在于两件事情:
用左边的折叠,累加器就是你丢弃的参数,所以每次你将(+1)
到列表中的下一个项目,并最终返回最后一个元素加上一个。
使用正确的折叠,累加器就是您保留的参数,所以每次您将(+1)
应用于之前的结果(从0开始并递增3次(对于列表中的每个项目))。
如果您使用更明显不同的输入值,可能会更容易看到这里发生了什么:
Prelude> foldl (_ -> (+1)) 100 [5,6,7]
8
Prelude> foldr (_ -> (+1)) 100 [5,6,7]
103
再次,“最后一个参数加一”和“列表长度加初始值”。
链接地址: http://www.djcxy.com/p/80725.html上一篇: foldl / foldr query