Hi, I’m lthms.

I don’t like syntax highlighting, but I like types and functional programming languages. He/him.

Interested in starting a discussion? Don’t hesitate to shoot me an email.

Writing a Function Whose Argument is a Polymorphic Function in OCaml

In OCaml, it is not possible to write a function whose argument is a polymorphic function. Trying to write such a function results in the type-checker complaining back at you.

let foo (type a b) id (x : a) (y : b) = (id x, id y)
Line 1, characters 50-51:
1 | let foo (type a b) id (x : a) (y : b) = (id x, id y);;
                                                      ^
Error: This expression has type b but an expression was expected of type a

When OCaml tries to type-check foo, it infers id expects an argument of type a because of id x, then fails when trying to type-check id y.

The trick to be able to write foo is to use records. Indeed, while the argument of a function cannot be polymorphic, the field of a record can. This effectively makes it possible to write foo, at the cost us a level of indirection.

type id = {id : 'a. 'a -> 'a}

let foo {id} x y  =
  (id x, id y)

From a runtime perspective, it is possible to tell OCaml to remove the introduced indirection with the unboxed annotation. There is nothing we can do in the source, though. We need to destruct id in foo, and we need to construct it at its call-site.

g {id = fun x -> x}

As a consequence, this solution is not a silver bullet, but it is an option that is worth considering if, e.g., it allows to export a cleaner API to the consumer of a modulePersonally, I have been considering this trick recently to remove the need for a library to be implemented as a functor.