equal (=) is already actually adhoc. And polymorphic types exist as ocaml encodes values to make it possible.
This breaks down if we want to build an alternative compiler which does not box and would be forced to transform generic polymorphism into adhoc one. Or another way to look at it, it’s like if generic functions depends on implicit modules which provides a set of primitive functions (equal, constructors, destructurers, …) which are solved for a given set of arguments (recursively if the function use other generic functions).
BTW How to make an highly efficient compiler if it really likes pointers because polymorphism is simpler to implement this way ?
Could you elaborate this? Not all values have a boxed representation in OCaml. However, OCaml values have a uniform runtime representation that enables polymorphism at the implementation level: a polymorphic function is compiled to a single function and typically does not branch on the runtime type of its arguments. Equality is an exception to this.
Indeed, there is the uniform representation which allows unboxed values at a price of one size for all. I glossed over it as my main focus was implicitly user-defined types.
If I want to have an array of record type, it seems to me generic polymorphism requires to have pointers, which is going to multiply cache lines and memory stalls. Thus an alternative compiler which tries to have polymorphic type depends on the layout/size of the parameter would require specialisation.
Generic polymorphism this way seems like void* polymorphism (qsort, …).
BTW How to make an highly efficient compiler if it really likes pointers because polymorphism is simpler to implement this way ?
You should checkout MLton which, by virtue of its whole-program compilation approach, can be very aggressive in its optimisations. In relation to data representations, it monomorphises functions and data types, going as far as to defunctionalise the functions (i.e. representing functions’s closures as algebraic datatypes in a first-order IR, with mutually recursive dispatchers). It does very well on numerous benchmarks - compared with other SML implementations - see Performance. It’s a very neat example of a heavily-optimising compiler for a functional programming language.
I don’t know of a canonical example, but this paper on a particular defunctionalisation technique/algorithm reports that certain benchmarks in OCaml are made to be between 1.08 and 3.45 times faster with it. (On pages 20 and 21 of that PDF.)
In C programming, it’s said that function pointers are slower than direct calls too. They make it harder to perform optimisations like inlining. The same thing applies more or less to non-defunctionalised closures because the typical implementation of a closure is a function pointer + some data (like partially applied arguments).