当列表包含零时,为什么 foldr 函数会给我一个否定的结果?

Why the foldr function gives me a negative result when the list contains a zero?

举个例子来说明我的意思

Prelude> foldr (-) 0 [0,1]  
-1

我以为这里基本上可以0 - 0 = 0; 1 - 0 = 1;但实际结果是-1

我用其他例子试过了

Prelude> foldr (-) 1 [1,3]   
-1

Prelude> foldr (-) 1 [1,9]
-7

我可能误解了 foldr 的工作原理,所以我很乐意得到解释:)

尝试foldr (-) 0 [1, 2, 3, 4, 5]。你应该得到 3。那是因为折叠等同于 (1 - (2 - (3 - (4 - (5 - 0)))))——它是从右边开始的。如果你尝试 foldl,你应该得到 -15。那是因为它是从左边开始的,相当于(((((0 - 1) - 2) - 3) - 4) - 5).

您的较短示例 foldr (-) 0 [0, 1] 等同于 0 - (1 - 0),后者缩减为 -1

考虑以下函数:

printfoldr f init xs = foldr (\el acc -> "(" ++ el ++ f ++ acc ++ ")") (show init) $ map show xs

此函数模拟 foldr 函数如何扩展和输出其字符串表示形式。

让我们运行进行一些测试:

λ> printfoldr "-" 0 [1,2,3,4]
"(1-(2-(3-(4-0))))"

-- the test cases you provided
λ> printfoldr "-" 0 [1,2]
"(1-(2-0))" -- This reduces to -1 which is the result you had

λ> printfoldr "-" 1 [1,3]
"(1-(3-1))" -- This reduces to -1 which is also the result you had

λ> printfoldr "-" 1 [1,9]
"(1-(9-1))" -- reduces -7 which is also correct

所以一般来说,foldr 类型 foldr :: (a -> b -> b) -> b -> t a -> b 的工作方式如下:

x0 `f` (x1 `f` ...(xn-2 `f` (xn-1 `f` (xn `f` init))))

其中 f(a -> b -> b) 类型,xa 类型,initb 类型。

foldr定义如下:

foldr f b [] = b
foldr f b (x:xs) = f x (foldr f b xs)

您递归地折叠列表的尾部,然后将 f 应用于头部和递归结果。请注意,基值用于序列的 end,而不是开头。

将其视为简单地将函数应用于一个接一个的值只有在 f 是关联的情况下才有效。例如,1 + (2 + (3 + 0)) == ((1+2) + 3) + 0.

但是,

减法 结合。一般来说,x - y - z只等于(x - y) - z,而不是x - (y - z)