I am a JavaScript programmer, and I have always argued that variational arguments are harmful . If we donβt have variational functions in JavaScript (just stay away from the arguments object), then every function in JavaScript typed in a system like Hindley Milner (minus API-specific functions like DOM functions) can easily be converted to an equivalent function at OCaml.
So what is the OCaml equivalent of the apply function? I believe this is a regular application:
let apply fx = fx (* equivalent of apply in JavaScript *)
How is a normal functional application equivalent to the apply function in JavaScript? Consider:
let sfgx = fx (gx) (* the S combinator from the SKI combinator calculus *)
This function will be written in JavaScript as follows:
var s = function (f) { return function (g) { return function (x) { return f(x)(g(x)); }; }; };
Note that each function definition and function call is explicitly written in curry.
This is the difference between JavaScript and OCaml:
- In OCaml, all functions have a default value, and you must not explicitly perform them.
- In JavaScript, all functions are not executed by default, and you must explicitly view them.
So, let's take a look at the irregular variations of the S-combinator. Firstly, OCaml:
let s (f, g, x) = f (x, g (x)) (* sml convention is to use uncurried functions *)
Equivalent in JavaScript:
var s = function (f, g, x) { return f(x, g(x)); };
Note that the regular function application is the same for OCaml and JavaScript. For curry functions:
let result = sfgx (* equivalent to `((sf) g) x` *)
Equivalent in JavaScript:
var result = s(f)(g)(x);
For irregular functions:
let result = s (f, g, x)
Equivalent in JavaScript:
var result = s(f, g, x);
What about the apply function? How is this equivalent to the normal use of a function?
In OCaml you can do this:
let args = (f, g, x) (* args is a tuple *) let result = s args (* normal function application *)
Equivalent in JavaScript:
var args = [f, g, x];
As you can see, tuples in OCaml are equivalent to arrays in JavaScript. Arrays in JavaScript are universal. They can be used as lists or tuples, depending on the context.
The args parameter assigned by apply can be any object, like an array, and is treated as a single tuple argument. Each function in JavaScript can be considered as one function of arguments. Multiparameter functions in JavaScript can be considered as a one-parameter function of a tuple argument. The apply JavaScript function is just a special form of application with a normal function.
And what does it mean? Consider:
var negate = function (f) { return function () { return !f.apply(null, arguments); }; };
If we consider arguments an implicit parameter of an internal function, then the equivalent of the above function in OCaml is:
let negate f = fun arguments -> not (f arguments) (* arguments is explicit *)
This can be simplified:
let negate fx = not (fx)
Now you can say that this will only work for single argument functions. This is not true. Typical negate signature:
val negate : ('a -> bool) -> 'a -> bool
Consequently, it can work for any type of 'a , including tuples. This is equivalent to JavaScript, in which multi-parameter functions are only one-parameter functions of tuple arguments.
Finally, the only real problem is converting curry functions to broken functions so you can negate them. Unfortunately, in OCaml there is no general way to decompose a function. So, you need a family of functions for uncurry curry functions of several arities:
let uncurry2 f (x, y) = fxy let uncurry3 f (x, y, z) = fxyz . . . .
After giving up functions, you can curry return them back. However, as with uncurry , there is no way for a universal curry function. Therefore, you will again need the curry family of functions:
let curry2 fxy = f (x, y) let curry3 fxyz = f (x, y, z) . . . .
The only way to create common curry or uncurry functions is to use dynamically typed languages ββ(like Lisp or JavaScript) or intrusive languages ββ(like Idris or Agda). The OCaml type system (Hindley Milner type system) is too restrictive to provide such functions.