Here’s a little trick that I find useful when I get a type error due to a function that I believe is polymorphic, but isn’t due to some bug. For example, suppose I had a function
f that I believed was of type
'a list -> 'a list, but really wasn’t.
let f x = 13 :: x (* suspend disbelief -- pretend f is large and complex *) let l = f ["foo"]
If I feed this to OCaml, I get an error message at the point
f is applied
This expression has type string but is here used with type int
I would like to find out what the error in
f is that makes it not polymorphic.
When I first came to OCaml from SML, I was surprised to find the following did
let f (x : 'a list) = 13 :: x let l = f ["foo"]
In SML, type variables in expressions are universally quantified (at a point
determined by some complex rules), while in OCaml they are not. So, while SML
would reject the definition of
f, OCaml happily unifies
In OCaml, one can get universally quantified type variables by using the signature language.
include (struct let f x = 13 :: x end : sig val f : 'a list -> 'a list end) let l = f ["foo"]
This fails with a more helpful error message.
Signature mismatch: Modules do not match: sig val f : int list -> int list end is not included in sig val f : 'a list -> 'a list end Values do not match: val f : int list -> int list is not included in val f : 'a list -> 'a list
However, it’s a lot of syntax to use the signature language, and can be
difficult if the function you want is not at the top level. Furthermore, you may
not want to write out the full type – perhaps you only want to add enough of a
constraint to catch the error. In SML, I just had to write the constraint on
and I was done. Fortunately, one can approximate the SML solution in OCaml by
using a new type that has no values.
type z let f (x : z list) = 13 :: x
This fails with an error message at the use of
x that is quite helpful.
This expression has type z list but is here used with type int list
f actually were polymorphic, then instantiating the polymorphism with a new
type should succeed, and I would get an error later in the code at a use of
So, using this trick I can now focus on
f until I fix all its type errors, at
which point I can remove the constraint and