Is it possible in F# to curry a middle function argument?
Here's code that works fine:
let f x y z = x + y + z
let g x y = f x y
let h x z = z |> f x
So I can write expression "h 1", and FSI displays:
val it : (int -> int -> int) = <fun:it@110-3>
If I call "h 1 2 3", the arguments are applied in the right order.
But if the last argument has a different type, things get different:let ff x y (z : string) = x + y
let gg x y = ff x y
let hh x (z : string) = z |> ff x
Now the last function hh causes an error message:
Scrip开发者_JAVA技巧t.fsx(119,10): error FS0001: Type mismatch. Expecting a
string -> 'a
but given aint -> string -> int
. The typestring
does not match the typeint
I understand why this happens - "z" is appended to "ff x" making it a second argument. But then I'd expect in the first example expression "h 1 2 3" not to work properly (being executed as "f 1 3 2"). But it works just fine.
The functions ff
and gg
in your example are the same - the pipelining operator provides value for a first argument of a function on the right-hand side. In your example, the function on the right hand side is ff x
and by using the pipelining operator, you specify the value for argument y
:
let ff x y (z : string) =
printfn "%s" z
x + y
// These two functions are the same:
let gg x y = ff x y
let hh x y = y |> ff x
There is no stnadard syntax for specifying other than first parameters when using partial function application. However, you can write a higher-order function or a custom operator to do that. 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 (|*>) v f = (fun mid -> f mid v);;
let gg x y = ff x y // Specifies arguments x and y
let hh x z = z |*> ff x // Specifies arguments x and z
I named the operator |*>
to denote that it skips one argument. You could define operators that specify value of other arguments similarly (e.g. |**>
to skip the first two arguments).
精彩评论