F#管道运算符如何工作

时间:2013-09-23 23:59:10

标签: f# pipeline

有一个代码:

 //e = 1/2*Sum((yi -di)^2)
    let error y d =
        let map = 
            Array.map2 (fun y d -> (y - d) ** 2.0) y d
        let sum = 
            Array.sum map
        (sum / 2.0)

    let error2 y d =
        Array.map2 (fun y d -> (y - d) ** 2.0) y d
        |> Array.sum
        |> (/) 2.0

我理解这些功能应该产生相同的结果,但结果有很大的不同。谁能解释一下呢?

P.S。简化示例:

let test = [|1..10|]
    let res = test
                |> Array.sum
                |> (/) 5

我希望test = 11(sum(1..10)= 55然后是55/5)但是在Array.sum管道不能正常工作之后(结果test = 0)。

3 个答案:

答案 0 :(得分:5)

另一种方法是使用反向管道运算符(< |),以便(/)的部分应用程序以正确的顺序使用参数完成:

let error2 y d =
    Array.map2 (fun y d -> (y - d) ** 2.0) y d
    |> Array.sum
    |> (/) <| 2.0

编辑:看看这是否有助于澄清

x/y = (/) x y = y |> (/) x = x |> (/) <| y

所有这些都是等价的。管道运算符定义为:

(|>) x f = f x
(<|) f x = f x

其中f是函数,x是某个值。反向管道看起来不是很多,但在某些情况下它可以帮助清理一些代码。

答案 1 :(得分:4)

您似乎误解了中缀函数中的参数顺序。

您可以按如下方式扩展无点表格:

x |> (/) 5
<=> (/) 5 x
<=> 5 / x

所以这与你的期望相反。它仅适用于(+)(*)等交换函数。如果您热衷于无点样式,flip函数有助于与{{1}一起使用}:

|>

答案 2 :(得分:1)

/运算符无法按照您的假设运行。您只需要更明确一点,并将error2中的最后一行更改为

fun t -> t/2.0

然后它应该全部工作。

这个问题的答案是4分。这里是赠品。

编辑:要了解/|>处发生了什么,请考虑展开a |> (/) b ((/) b) a //by removing |> a / b //what happens when / is reinterpreted as a function 时会发生什么

以下都是等效的

{{1}}