Ilya Kharlamov
Ilya Kharlamov

Reputation: 3932

F# Partially apply the second argument

in F# if I take a function that takes two arguments, for example, mod (%):

13 % 10
// val it : int = 3

which is the same as

(%) 13 10
// val it : int = 3

is there any way to write it in the pipe notation, currying the 13?

Obviously, the “two-argument function” is actually a one-argument function that returns an intermediate function. So can pipe

10 |> (%) 13
// val it : int = 3

However, I need the other way around, i.e. pipe the first argument 13, having the second argument 10 partially applied, but not the first one.

Is there anything in the language that helps to do that, without creating extra lambdas every time, i.e. to avoid the following?

13 |> (fun x -> x % 10)

Upvotes: 6

Views: 1471

Answers (4)

Soldalma
Soldalma

Reputation: 4758

F# already contains an operator that will do what you want, namely <|:

10 |> (%) <| 13;;
val it : int = 10

This is equivalent to

(10 |> (%)) 13;;
val it : int = 10

Upvotes: 2

Fyodor Soikin
Fyodor Soikin

Reputation: 80754

There is no built-in, standard way to do this. Moreover, due to how function application works, it's impossible to do so: as soon as you write (%) 13, you've already applied the first argument, because function application has the highest and non-configurable precedence in F#.

You can, if course, make yourself a special function to produce a "weird" function application - one that would apply the second argument and leave a hole for the first:

let ap f x = fun y -> f y x

And then:

let x = 13 |> ap (%) 10
> x : int = 3

Incidentally, the function ap is a semi-standard occurrence in ML languages, and is usually called flip, because what it does is "flipping" the order of the arguments:

let flip f x y = f y x

Or, you can even make it into an operator:

let (-*-) = flip

And then:

let x = 13 |> (%) -*- 10
> x : int = 3

However, this sort of trickery gets unreadable very quickly. In practice, it is far more preferable to just declare a function that does what you need:

let mod10 x = x % 10

And then:

let x = 13 |> mod10

Or, if you really need it to be very general:

let mod' x y = y % x

And then:

let x = 13 |> mod' 10

Upvotes: 7

Terrance
Terrance

Reputation: 11872

K, you are looking for a flip

let flip f a b = f b a

Upvotes: 1

Mankarse
Mankarse

Reputation: 40623

You can write a combinator that will do this for any function of two arguments:

let inline flip f y x = f x y

This can be used as:

13 |> flip (%) 10

Upvotes: 4

Related Questions