如何折叠 Double 类型的列表?

How do I foldr a list of type Double?

我正在编写一些代码,我需要折叠一个双打列表,但是,即使是这一行简单的代码也会出现我无法理解的错误,即:

Couldn't match expected type ‘Double’
            with actual type ‘t0 [t1] -> [t1]’
Probable cause: ‘foldr’ is applied to too few arguments
In the expression: foldr (+) [3.3, 1.4, 5.5]
In an equation for ‘foldDoubles’:
    foldDoubles = foldr (+) [3.3, 1.4, 5.5]

举个简单的例子:

foldDoubles = foldr (+) [3.3, 1.4, 5.5]

整数的示例格式相同,所以我不明白为什么会有 "too few arguments",我需要进行某种转换吗?

Probable cause: ‘foldr’ is applied to too few arguments

因为foldr应用于参数太少。观察到:

foldr (+) [3.3, 1.4, 5.5]
--     one  two

但是:

:type foldr
Foldable t => (a -> b -> b) -> b -> t a -> b
--              one            two  three

您缺少 b 类型的参数。在这种情况下,你似乎想要一个总和,所以也许你想使用零作为累加器开始你的折叠:

foldr (+) 0 ...

foldr 函数的类型为 Foldable t => (a -> b -> b) -> b -> t a -> b,其中包含三个参数((a -> b -> b)bt a),而您只包含两个争论。我们可以重写 foldDoubles 以通过添加 b 类型的基本情况来保存我们为单个硬编码列表计算的折叠来修复此错误:

foldDouble = foldr (+) 0 [3.3, 1.4, 5.5]

但让我们看得更远一点。我们可以制作一个接受列表的通用函数,而不是对列表进行硬编码 [3.3, 1.4, 5.5],并且 returns 它是总和(这只是求和函​​数):

foldDouble xs = foldr (+) 0 xs

我们可以在一般列表上使用它,就像我们的 Prelude 定义的求和函数一样:

ghci>> foldDouble [3.3, 1.4, 5.5]
10.2

接下来,我们可以减少 eta-reduce 以获得更简洁的形式:

foldDouble = foldr (+) 0

最后,有一个方便的函数 foldr1 允许我们摆脱我们的基本情况(列表中的最后一个元素被假定为基本情况)。使用这个函数,我们可以去掉 0:

foldDouble = foldr1 (+)