为什么不能关闭多态变体的子集类型检查超集?

时间:2015-06-28 19:38:45

标签: ocaml

变体[`A | `B][`A | `B | `C]

等超集不兼容

我知道他们无法统一,除非>被添加到子集或<添加到超集,但我很好奇是否有一个示例接受这种类型的输入可能导致错误的程序。

用这样一个非常简单的用法:

let return_a : bool -> [ `A ] = fun _ -> `A

let foo : bool -> [ `A | `B ] = return_a

接受实现似乎是完全安全的,因为foo的声明类型是实现类型(return_a的类型)的严格超集。但是(如预期的那样)它不会输入检查:

Error: This expression has type bool -> [ `A ]
but an expression was expected of type bool -> [ `A | `B ]
The first variant type does not allow tag(s) `B

实际上它看起来比

更具限制性
let return_a : bool -> [ `A ] = fun _ -> `A

let foo : bool -> [< `A | `B ] = return_a

哪种类型检查。

这种对多态变体使用的限制只是对类型推断如何工作的限制,还是有一个实际的理由将第一个片段标记为错误类型?

1 个答案:

答案 0 :(得分:4)

类型[`A | `B][`A | `B | `C]的子类型。 OCaml支持子类型,但它必须是显式的。

# type abc = [`A | `B | `C];;
type abc = [ `A | `B | `C ]
# type ab = [`A | `B];;
type ab = [ `A | `B ]
# let f (x: abc) = 14;;
val f : abc -> int = <fun>
# let (x: ab) = `A;;
val x : ab = `A
# f x;;
Error: This expression has type ab but an expression was expected of type abc      
       The first variant type does not allow tag(s) `C
# f (x :> abc);;
- : int = 14
#