如何使用foldl与operator

时间:2017-12-24 00:26:29

标签: haskell

我认为两个代码应该正常运行

[]

但我得错误使用foldl:

foldr (:) [] [1..5]
foldl (:) [] [1..5]

为什么foldl不能运行?

3 个答案:

答案 0 :(得分:4)

foldlfoldr的类型签名在函数参数中略有不同(它们已切换参数):

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

foldrfoldl之间的巨大差异是运算符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是列表 - 列表清单等等。