I have defined a buggy function:
let first : 'a -> 'b -> 'a = fun x y -> y ;;
(* Result: val first : 'a -> 'a -> 'a = <fun> *)
The compiler accepts it and changes the type from 'a->'b->'a to 'a->'a->'a.
It should not work because the return type should be 'a, not 'b.
Correct implementation:
let first : 'a -> 'b -> 'a = fun x y -> x ;;
(* Result: val first : 'a -> 'b -> 'a = <fun> *)
Why does it work and how to prevent the compiler from changing the type like so? It becomes a problem with more complex expressions.
By default, types variables in explicit annotations in OCaml are unification variables. In particular, they can be useful to add some equality constraints. For instance, the
'aannotation shared byxandyallows the compiler to detect that inthe case
is missing but that would not work without refining the type variable
'ato the quite complicated type ofx.The issue is thus that annotation is not the one that you wanted. If you want to enforce that a function has the polymorphic type
'a -> 'b -> 'a, you can use an explicit universal quantification:With this annotation, the typechecking fails with an error:
as expected. Whereas the correct function
compiles without troubles.
Here, the prefix
type a b.reads "for all possible typesaandb" and this annotation enforces that the type offwill be equal to'a -> 'b -> 'awithout any refinement (aka unification) of the type variables'aand'b.