【问题标题】:F# function composition where the first function has arity >1F# 函数组合,其中第一个函数的元数 >1
【发布时间】:2015-10-12 16:35:43
【问题描述】:

我有两个函数fg

let f (x:float) (y:float) = 
    x * y

let g (x:float) = 
    x * 2.0

我想组合(>>)它们以获得一个新函数,该函数执行f,然后在结果上执行g

解决方案的行为应该是:

let h x y = 
    (f x y) |> g

这不起作用:

// Does not compile
let h = 
    f >> g

>>应该如何使用?

【问题讨论】:

    标签: function f# function-composition first-class-functions


    【解决方案1】:

    我想你想实现这个:

    let fog x  =  f x >> g 
    

    你不能直接按 f >> g 的顺序组合它们,这是有道理的,因为 f 需要两个参数,所以这样做 f x 将导致部分应用函数,但 g 需要一个值,而不是函数.

    以相反的方式组合工作,在您的特定示例中,您甚至会得到相同的结果,因为您使用的是交换函数。您可以执行 g >> f 并得到一个导致部分应用函数的组合,因为 g 需要一个值,因此通过将一个值应用于 g 您会得到另一个值(不是函数)并且 f 需要两个值,那么你将得到一个部分应用的函数。

    【讨论】:

      【解决方案2】:

      以无点风格编写,即定义没有显式参数的函数,当隐式参数超过一个时会变得丑陋。

      使用正确的运算符组合总是可以做到的。但结果会令人失望,您将失去无点样式的主要好处 - 简单易读。

      为了乐趣和学习,我们会试一试。让我们从显式(又名“pointful”)风格开始,然后从那里开始工作。

      (注意:我们将把我们的组合运算符重新排列成它们的显式形式(>>) (a) (b),而不是更常见的a >> b。这会创建一堆括号,但它会让事情更容易理解,不用担心关于有时不直观的运算符优先规则。)

      let h x y =  f x y |> g
      
      let h x = f x >> g
      
      // everybody puts on their parentheses!
      let h x = (>>) (f x) (g)
      
      // swap order
      let h x = (<<) (g) (f x)
      
      // let's put another pair of parentheses around the partially applied function
      let h x = ((<<) g) (f x)
      

      我们来了!看,现在h x 以我们想要的shape 表示——“将x 传递给f,然后将结果传递给另一个函数”。

      该函数恰好是((&lt;&lt;) g),该函数将float -&gt; float 作为参数并返回其与g 的组合。

      g 出现的组合,这很重要,即使在使用的特定示例中也没有什么区别。)

      我们的float -&gt; float 参数当然是(f x),即f 的部分应用。

      所以,以下编译:

      let h x = x |> f |> ((<<) g)
      

      现在可以很清楚地简化为

      let h = f >> ((<<) g)
      

      当您已经知道它的含义时,这并不是所有的 看起来很糟糕。但是任何有理智的人都更愿意写和阅读let h x y = f x y |&gt; g

      【讨论】:

        猜你喜欢
        • 2018-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-21
        相关资源
        最近更新 更多