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>
5 回答
在
foldl
情况下,lambda作为第一个参数传递累加器,而第二个参数传递list元素 . 在foldr
情况下,lambda作为第一个参数传递list元素,第二个参数传递累加器 .你的lambda忽略第一个参数,并在第二个参数中加1,所以在
foldl
情况下你将1加到最后一个元素,而在foldr
情况下,你正在计算列表中元素的数量 .那是因为参数的顺序在
foldl
中翻转 . 比较他们的类型签名:所以你看,在使用
foldl
的代码中,你重复递增累加器,忽略列表 . 但是在带有foldr
的代码中,你甚至都没有触及累加器,只是增加了列表的元素 . 由于最后一个元素是3
,结果是3 + 1 = 4
.如果您使用字符列表而不是字符串,您可以更容易地看到您的错误:
不同之处在于两件事:
您正在丢弃累加功能的一个输入并将常量功能应用于另一个 .
累加函数的参数顺序在两者之间是不同的 .
使用左侧折叠,累加器是您丢弃的参数,因此每次将
(+1)
应用于列表中的下一个项目并最终返回最后一个元素加一个 .使用右侧折叠,累加器是您保留的参数,因此每次将
(+1)
应用于上一个结果时,该值为0并且开始增加三次(对于列表中的每个项目) .如果你使用更明显不同的输入值,可能更容易看到这里发生了什么:
再次,“最后一个参数加一个”和“列表长度加上初始值” .
在
foldl f
中,累加器是f
的左参数,您忽略它,因此返回1 +
最后一个元素 . 对于foldr
,累加器是正确的参数,因此您将每个项目的累加器增加1,从而有效地给出列表的长度 .去除currying和point自由样式可能会有所帮助 . 你的两个表达式是等效的:
当这样看时,结果应该显得更加明显