Hello! I stumbled on a type error in OCaml 4.14 using polymorphic variants with [< .. ]
variance in the signature of a module. In the implementation I match on the polymorphic variant in a function with a wildcard pattern and then I get a confusing type error. However, if I spell out the cases I don’t get a type error. I don’t quite understand.
Here it fails:
module M : sig
val f : [< `Read | `Write ] -> int -> unit
end = struct
let f mode len =
match mode with
| `Write -> print_endline (String.make (max 0 (pred len)) 'E')
| _ -> ignore (input_line stdin)
end
And the type error is the following:
Error: Signature mismatch:
Modules do not match:
sig val f : [> `Write ] -> int -> unit end
is not included in
sig val f : [< `Read | `Write ] -> int -> unit end
Values do not match:
val f : [> `Write ] -> int -> unit
is not included in
val f : [< `Read | `Write ] -> int -> unit
The type [> `Write ] -> int -> unit is not compatible with the type
[< `Read | `Write ] -> int -> unit
The tag `Write is guaranteed to be present in the first variant type,
but not in the second
Changing the _
pattern to `Read
the compiler is happy again.
module M : sig
val f : [< `Read | `Write ] -> int -> unit
end = struct
let f mode len =
match mode with
| `Write -> print_endline (String.make (max 0 (pred len)) 'E')
| `Read -> ignore (input_line stdin)
end
Edited to add:
Adding a type ascription in the implementation does not change anything:
module M : sig
val f : [< `Read | `Write ] -> int -> unit
end = struct
let f (mode : [< `Read | `Write ]) len =
match mode with
| `Write -> print_endline (String.make (max 0 (pred len)) 'E')
| _ -> ignore (input_line stdin)
end