【问题标题】:"summing" functions in F#F# 中的“求和”函数
【发布时间】:2016-04-12 19:29:34
【问题描述】:

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

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

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

【问题讨论】:

  • 地图/折叠 -> 折叠/总和?添加一些代码将是有益的,包括已尝试的任何 [HoF] 用法以及当前的“非通用”方法。

标签: f# inline


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 可以简化为免积分版:let inline sumAll() = (|||>) >> List.sumBy
【解决方案2】:
let sumAll (fs: (float -> float -> float -> float) list) a b c = List.map (fun f -> f a b c) fs |> Seq.sum

【讨论】:

    【解决方案3】:

    @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
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-03
      • 2012-07-18
      相关资源
      最近更新 更多