Is it possible in F # to align the argument of a middle function?

Here is the code that works fine:

let fxyz = x + y + z let gxy = fxy let hxz = z |> fx 

Therefore, I can write the expression "h 1", and FSI displays:

 val it : (int -> int -> int) = <fun:it@110-3> 

If I call "h 1 2 3", the arguments will be applied in the correct order.
But if the last argument is of a different type, everything becomes different:

 let ff xy (z : string) = x + y let gg xy = ff xy let hh x (z : string) = z |> ff x 

Now the last hh function raises an error message:

Script.fsx (119.10): error FS0001: type mismatch. Expecting a string -> 'a but given int -> string -> int . string type does not match int type

I understand why this happens - "z" is added to "ff x", which makes it the second argument. But then I would expect that in the first example the expression "h 1 2 3" would not work properly (executed as "f 1 3 2"). But it works just fine.

+7
currying f #
source share
1 answer

The ff and gg functions are the same in your example - the pipeline operator provides the value for the first argument of the function to the right. In your example, the function is on the right side of ff x , and using the pipelining operator, you specify the value for the y argument:

 let ff xy (z : string) = printfn "%s" z x + y // These two functions are the same: let gg xy = ff xy let hh xy = y |> ff x 

There is no stnadard syntax for specifying parameters other than the first when using a partial function application. However, for this you can write a higher order function or a custom operator. For example:

 // Takes a function 'f' of type 'b -> 'a -> 'c // and a value 'v' of type 'a and creates a function // that takes the first argument ('b -> 'c) let (|*>) vf = (fun mid -> f mid v);; let gg xy = ff xy // Specifies arguments x and y let hh xz = z |*> ff x // Specifies arguments x and z 

I called the |*> operator to indicate that it skips one argument. You can define operators that likewise match the value of other arguments (for example, |**> to skip the first two arguments).

+8
source share

All Articles