Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

currying

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.

like image 340
Pteromys Avatar asked Mar 10 '12 14:03

Pteromys


People also ask

How do you make an optional argument a function?

You can assign an optional argument using the assignment operator in a function definition or using the Python **kwargs statement. There are two types of arguments a Python function can accept: positional and optional. Optional arguments are values that do not need to be specified for a function to be called.

Are function call arguments optional?

So, it is optional during a call. If a value is provided, it will overwrite the default value. Any number of arguments in a function can have a default value. But once we have a default argument, all the arguments to its right must also have default values.

What does fun mean in OCaml?

Similarly, OCaml functions do not have to have names; they may be anonymous. For example, here is an anonymous function that increments its input: fun x -> x + 1 . Here, fun is a keyword indicating an anonymous function, x is the argument, and -> separates the argument from the body.


1 Answers

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.

like image 168
gasche Avatar answered Jan 03 '23 10:01

gasche