我在F#中有一个函数列表,它们都是类型(float - > float - > float - > float)。我想在序列上进行某种折叠以获得一个函数,该函数返回所有函数的总和。
例如,我可以将值1.0,2.0和3.0传递给列表中的每个函数,并从每个函数中获取返回值。然后我可以计算所有这些值的总和。但是,我想概括一下。
我知道如何递归地执行此操作,但我觉得它应该在一行中可行。有没有简洁的方法来完成这项任务?
答案 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
键入整个类型规范要短。