Typing (function `A -> 1 | _ -> 0) is reasonable, as Geoffrey explained. Reason for which
(function `A -> 1 | _ -> 0) ((fun x -> (match x with `B -> ()); x) `B)
does not check the type, it should be explained, in my opinion, the last part of the expression. Indeed, the function (fun x -> (match x with `B -> ()); x) has an input type [< `B] , and its parameter `B has a type [> `B ] . Combining both types produces a private type [ `B ] that is not polymorphic. It cannot be unified with the input type [> `A ] that you get from (function `A -> 1 | _ -> 0) .
Fortunately, polymorphic variants not only rely on (in-line) polymorphism. You can also use subtyping in situations where you want to increase the private type: [ `B ] is a subtype, for example, [`A | `B] [`A | `B] , which is an instance of [> `A ] . Subtype assignment is explicit in OCaml using the syntax (expr :> ty) (casting for some type) or (expr : ty :> ty) if the domain type cannot be correctly inferred.
You can write:
let b = (fun x -> (match x with `B -> ()); x) `B in (function `A -> 1 | _ -> 0) (b :> [ `A | `B ])
which is well typed.
source share