3
votes

have a code:

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

as i understood those functions should produce the same results, but there are a big difference in the results. Can anyone explain this?

p.s. Simplified example:

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

i expect test = 11 (sum(1..10) = 55 and then 55 / 5) but after Array.sum pipeline is not working as i want(as result test = 0).

3

3 Answers

1
votes

The / operator does not work the way you have assumed. You just need to be a bit more explicit and change the last line in error2 to

fun t -> t/2.0

and then it should all work.

The answers being out by a factor of 4 was the giveaway here.

EDIT: To understand what happens with / here consider what happens when you expand out |>

The following are all equivalent

a |> (/) b
((/) b) a //by removing |>
a / b     //what happens when / is reinterpreted as a function
5
votes

another alternative is to use the reverse pipe operator (<|) so that partial application of (/) is done with arguments in correct order:

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

Edit: see if this helps clarify

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

All those are equivalent. The pipe operators are defined as:

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

where f is a function and x is some value. The reverse pipe doesn't look like it does much but it can help clean up some code in certain situations.

4
votes

You seem to misunderstand order of arguments in infix functions.

You can expand the point-free form as follows:

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

So it's is the reverse of what you expect. It only works fine for commutative functions like (+), (*), etc. If you're keen on point-free style, the flip function is helpful to be used with |>:

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