3

有一个代码:

 //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

据我了解,这些功能应该产生相同的结果,但结果有很大差异。谁能解释一下?

ps 简化示例:

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

我期望 test = 11 (sum(1..10) = 55 然后 55 / 5) 但是在 Array.sum 管道没有按我想要的那样工作之后(结果 test = 0)。

4

3 回答 3

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 是某个值。反向管道看起来没有多大作用,但它可以在某些情况下帮助清理一些代码。

于 2013-09-24T17:18:13.453 回答
4

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

您可以按如下方式展开无点形式:

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

所以这与你所期望的相反。它只适用于 , 等交换函数(+)(*)如果您热衷于无点风格,该flip函数有助于与 一起使用|>

let inline flip f x y = f y x

let error2 y d =
    Array.map2 (fun y d -> (y - d) ** 2.0) y d
    |> Array.sum
    |> flip (/) 2.0
于 2013-09-24T09:38:02.247 回答
1

/操作员不会按照您假设的方式工作。您只需要更明确一点,并将 error2 中的最后一行更改为

fun t -> t/2.0

然后它应该一切正常。

答案是 4 倍是这里的赠品。

编辑:要了解/此处发生的情况,请考虑扩展时会发生什么|>

以下都是等价的

a |> (/) b
((/) b) a //by removing |>
a / b     //what happens when / is reinterpreted as a function
于 2013-09-24T00:03:17.380 回答