2

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

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

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

4

3 回答 3

8

@Lee 的解决方案是您正在寻找的单线。如果您想保存一些字符,您可以使用List.sumBywhich 首先将给定函数应用于列表的元素(类似于List.map),然后对结果求和(就像List.sum):

let sumAll (fs:(_ -> _ -> _ -> float) list) a b c = 
  List.sumBy (fun f -> f a b c) fs

这个版本和 Lee 的版本都使用类型注释来指定列表中的函数 return float。这是必需的,因为否则编译器不知道您要使用哪种数字求和List.sum(浮点数、整数等)。需要解决这种歧义以编译该函数。

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

let inline sumAll a b c = List.sumBy (fun f -> f a b c)

现在您可以使用流水线调用它,如下所示 fs |> sumAll 1 2 3

于 2013-01-15T20:39:53.453 回答
4
let sumAll (fs: (float -> float -> float -> float) list) a b c = List.map (fun f -> f a b c) fs |> Seq.sum
于 2013-01-15T20:13:40.697 回答
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)

一种支持咖喱参数的更易读的方式:

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

请注意,我使用类型参数 onList.sumBy因为它看起来比为f.

于 2013-01-16T01:40:04.103 回答