Pteromys
Pteromys

Reputation: 1481

How to curry a function w.r.t. its optional arguments in OCaml

Suppose a function bind has a labelled argument, optional arguments and unlabelled arguments, and you want to define a method m that applies the unlabelled arguments of bind and returns the partially applied function, so that the user of m can apply the labelled or optional arguments of bind. How do you do this? Simply writing method m = bind a b [...] z causes the compiler to think that the optional arguments are omitted.

Upvotes: 5

Views: 1485

Answers (1)

gasche
gasche

Reputation: 31459

The position of the optional arguments (in the function declaration or function type) is important: they are only applied implicitly when the next non-optional argument is applied.

If you want the partial application of one parameter p to not apply an optional parameter ?o, put ?o after p in the function declaration.

Contrast

# let f ?o p ~z = ();;
val f : ?o:'a -> 'b -> z:'c -> unit = <fun>
# f 1;;
- : z:'_a -> unit = <fun>  (* ?o applied *)

with:

# let f p ?o ~z = ();;
val f : 'a -> ?o:'b -> z:'c -> unit = <fun>
# f 1;;
- : ?o:'_a -> z:'_b -> unit = <fun> (* ?o not applied *)

If you don't want to change the definition order, or want to partially apply all non-optional parameters, you need to explicitly capture the optional parameters that would be implicitly passed:

# (fun ?o () -> f ?o 1 ~z:2);;
- : ?o:'a -> unit -> unit = <fun>

In case you weren't familiar with it, the ?o syntax at call site is very handy for this: it takes an 'a option and does the right thing to transparently pass an optional argument, whether applied or not, to the callee.

I have added a last () parameter to preserve the property that there is at least one non-optional argument after the optional ones. It is possible to not do this, but it gets tricky and is not advised.

Upvotes: 11

Related Questions