F#中的“求和”函数

时间:2013-01-15 20:08:13

标签: f# inline

我在F#中有一个函数列表,它们都是类型(float - > float - > float - > float)。我想在序列上进行某种折叠以获得一个函数,该函数返回所有函数的总和。

例如,我可以将值1.0,2.0和3.0传递给列表中的每个函数,并从每个函数中获取返回值。然后我可以计算所有这些值的总和。但是,我想概括一下。

我知道如何递归地执行此操作,但我觉得它应该在一行中可行。有没有简洁的方法来完成这项任务?

3 个答案:

答案 0 :(得分:8)

@Lee的解决方案是您正在寻找的一个班轮。如果要保存几个字符,可以使用List.sumBy首先将给定函数应用于列表元素(类似于List.map),然后对结果求和(就像{{1}一样) }):

List.sum

这个和Lee的版本都使用类型注释来指定列表中的函数返回let sumAll (fs:(_ -> _ -> _ -> float) list) a b c = List.sumBy (fun f -> f a b c) fs 。这是必需的,因为否则编译器不知道要使用float(浮点数,整数等)求和的数字类型。需要解决这种歧义来编译函数。

或者,您可以将函数标记为List.sum,然后在调用它时将其内联(并且它适用于多种不同的数字类型)。您还可以将inline参数作为最后一个参数传递,并使用部分函数应用程序:

fs

现在您可以使用管道传输来调用它,如下所示:let inline sumAll a b c = List.sumBy (fun f -> f a b c)

答案 1 :(得分:4)

let sumAll (fs: (float -> float -> float -> float) list) a b c = List.map (fun f -> f a b c) fs |> Seq.sum

答案 2 :(得分:4)

@ Lee和@Tomas的答案很棒,但还有一个较短的方法。

如果您能够在调用时将(a, b, c)作为三倍传递:

let inline sumAll() = (|||>) >> List.sumBy
// usage
let predicates =
    [
        fun a b c -> a
        fun a b c -> b * 42.0 - c
    ]
let ret1 = predicates |> sumAll()(1.0, 2.0, 3.0)

它也是通用的:

let predicates2 =
    [
        fun a b c -> c - 10
        fun a b c -> a + c * 42
    ]
let ret2 = predicates2 |> sumAll()(1, 2, 3)

一种更易读的方式,支持curried参数:

let sumAllCurried a b c = (a,b,c) |> (|||>) |> List.sumBy<_, float> 
// usage
let ret3 = predicates |> sumAllCurried 1.0 2.0 3.0

注意,我在List.sumBy上使用了类型参数,因为它看起来比为f键入整个类型规范要短。