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