It's been a while since I've coded OCaml, and I came across this problem which sounds simple but I'm having a mental block with solving:
Write a function that takes in a function f with a variable number of arguments that returns a boolean (i.e. f is of type 'a -> 'b -> 'c -> ... -> bool) and returns a function g that represents the negation of f (i.e. (f x1 x2 .. xn) == not (g x1 x2 .. xn) for all valid parameter sets).
It was inspired by the following code block which solves the problem in Javascript:
function negate(func) {
return function() {
return !func.apply(null, arguments);
};
}
(from http://eloquentjavascript.net/1st_edition/chapter6.html)
However, I don't see a way to implement this in OCaml (the "arguments" keyword or equivalent is not available) because of the fact that the function f has no preset number of arguments. I have found links that talk about dealing with functions with variable numbers of arguments (such as https://blogs.janestreet.com/variable-argument-functions/) but I would like to know if there is a simpler / more 'natural' way to deal with this specific problem.
I am a JavaScript programmer and I have always maintained that variadic arguments are harmful. If we don't have variadic functions in JavaScript (just stay away from the
argumentsobject), then every function in JavaScript typable in the Hindley Milner type system (minus API specific functions, like DOM functions) can be easily converted into an equivalent function in OCaml.So what's the OCaml equivalent of the
applyfunction? I believe that it's normal function application:How is normal function application equivalent to the
applyfunction in JavaScript? Consider:This function would be written in JavaScript as follows:
Note that every function definition and function call is explicitly written in curried form.
This is the difference between JavaScript and OCaml:
So, let's take a look at the uncurried variants of the S combinator. First, OCaml:
The equivalent in JavaScript:
Note that normal function application is the same in both OCaml and JavaScript. For curried functions:
The equivalent in JavaScript:
For uncurried functions:
The equivalent in JavaScript:
So what about the
applyfunction? How is that equivalent to normal function application?In OCaml, you can do this:
The equivalent in JavaScript is:
As you can see tuples in OCaml are equivalent to arrays in JavaScript. Arrays in JavaScript are versatile. They can be used as either lists or tuples, depending upon the context.
The
argsparameter given toapplycan be any array-like object and it's treated as a single tuple argument. Every function in JavaScript can be thought of as a single argument function. Multi-parameter functions in JavaScript can be thought of as a single-parameter tuple argument function. Theapplyfunction of JavaScript is just a special form of normal function application.So what does this imply? Consider:
If we consider
argumentsto be an implicit parameter of the inner function then the equivalent of the above function in OCaml is:This can be simplified to:
Now, you might say that this will only work for single argument functions. That's not the case. The type signature of
negateis:Hence, it can work for any type
'aincluding tuples. This is equivalent to JavaScript in which multi-parameter functions are just single-parameter tuple argument functions.Finally, the only real problem is converting curried functions into uncurried functions so that you can
negatethem. Unfortunately, there's no generic way of uncurrying a function in OCaml. So you need a family of functions touncurrycurried functions of several arities:After negating the functions you can
currythem back. However, just as withuncurrythere's no way to genericallycurrya function. Hence, you again need a family ofcurryfunctions:The only way to create generic
curryoruncurryfunctions is to use dynamically typed languages (like Lisp or JavaScript) or dependently typed languages (like Idris or Agda). The type system of OCaml (the Hindley Milner type system) is too restrictive to allow such functions.