我认为两个代码应该正常运行
[]
但我得错误使用foldl:
foldr (:) [] [1..5]
foldl (:) [] [1..5]
为什么foldl不能运行?
答案 0 :(得分:4)
foldl
和foldr
的类型签名在函数参数中略有不同(它们已切换参数):
foldl :: (b -> a -> b) -> b -> t a -> b
foldr :: (a -> b -> b) -> b -> t a -> b
要让foldl
工作,您可以使用flip
交换函数的参数:
flip :: (a -> b -> c) -> b -> a -> c
即。这应该有效:
foldl (flip (:)) [] [1..5]
答案 1 :(得分:1)
让我们从它的等式开始:
foldl :: (b -> a -> b) -> b -> [a] -> b
foldl op z [] = z
foldl op z (x:xs) = foldl op (op z x) xs
foldr
和foldl
之间的巨大差异是运算符op
如何工作:foldl
是尾递归的,并且从左到右应用运算符,而不是{{ 1}}是反对的。
所以,你可能想要的是:
foldr
可以使用foldl (\(currentFold, element) -> element:currentFold) [] [1,2,3,4,5]
进行美化(如@mschmidt指出的那样)
回想一下flip
方程:
foldr
会略有不同:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr op z [] = z
foldr op z (x:xs) = op x (foldr op z xs)
与您发布的内容相同:
foldr (\(element, currentFold) -> element:currentFold) [] [1,2,3,4,5]
答案 2 :(得分:1)
了解它的另一种方法是:
foldr (:) [] [1..5]
装置
1 : (2 : (3 : (4 : (5 : []))))
,而
foldl (:) [] [1..5]
装置
(((([] : 1) : 2) : 3) : 4) : 5
后者没有意义:使用数字就好像它们是列表一样。此外,:
的每次使用都会更改输出的类型([]
是列表,[]:x
是列表列表,([]:x):y
是列表 - 列表清单等等。