I have the following code:
module Test : sig
type +'a t
val make : int -> [< `a | `b] t
end = struct
type 'a t = Foo of int | Bar of string
let make = function
| 0 -> (Foo 0 : [`a] t)
| _ -> (Bar "hi" : [`a] t)
end
As you may note, the abstract type 'a t is declared as being covariant in its type parameter 'a, and the make constructor is declared as returning a subtype of the polymorphic variant cases a or b.
In my implementation of make, returning a subtype [a] t should still follow the covariance rule since the subtype is in the return type position.
However, I get the following error:
Error: Signature mismatch:
...
Values do not match:
val make : int -> [ `a ] t
is not included in
val make : int -> [< `a | `b ] t
File ".../cov.ml", line 3, characters 3-34:
Expected declaration
File ".../cov.ml", line 7, characters 7-11:
Actual declaration
Any suggestions on how to convince OCaml that the make function really is returning a valid subtype of [a | b] t?
I did some experiments:
So, apparently OCaml does recognize the supertype relationship but still prefers to stick to the more exact subtype unless given a coercion. Others may know the type theoretic reasons. But as your question was just
my answer is: Use coercions like so