I am following along with the section on polymorphic variants in RWO. Specifically, I am playing with this .mli
file and this .ml
file, except I changed the definition of extended_color_to_int
in variants-termcol-fixed.ml
to be
let extended_color_to_int = function
| `RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216
| `Grey x -> 2000 + x
| (`Basic _ | `RGB _ | `Gray _) as color -> color_to_int color
Just like it says in RWO, this function definition compiles without error, even though we’ve inadvertently added a new polymorphic variant constructor by misspelling “Gray” as “Grey”. In order to get an error, we have to explicitly add a type annotation:
let extended_color_to_int : extended_color -> int = function
Why? As I understand it, the type definition in variants-termcol-fixed.mli
defines the exact tags that are a part of the type extended_color
, so a function that pattern matches on a value of type extended_color
would have to match that exact set of tags, no more, no less. And we’ve also explicitly stated in the .mli
that extended_color_to_int
takes a value of type extended_color
. Nonetheless, RWO explains: “All that happened was that the compiler inferred a wider type for extended_color_to_int, which happens to be compatible with the narrower type that was listed in the mli.” If we really have specified the exact set of tags that are allowed to be included in the type extended_color
, then why is the compiler allowed to infer a “wider type”, and how can this type be “compatible” with the type we’ve supplied?