多态变体和类型签名
Polymorphic variants and type signatures
(这是 的扩展/提炼)
考虑以下代码:
版本 1:
let x : [> `Error1 ] = (`Error1 : [> `Error1 ])
let y : [> `Error1 | `Error2 ] = x
版本 2:
let x : [> `Error1 ] = (`Error1 : [ `Error1 ])
let y : [> `Error1 | `Error2 ] = x
版本 1 类型检查,但版本 2 失败(我正在使用 4.09.0 进行编译):
File "test.ml", line 2, characters 33-34:
2 | let y : [> `Error1 | `Error2 ] = x
^
Error: This expression has type [ `Error1 ]
but an expression was expected of type [> `Error1 | `Error2 ]
The first variant type does not allow tag(s) `Error2
注意这个错误出现在y
的定义中,但是x
的签名在这两种情况下是一样的! y
怎么能看到x
的定义里面呢?关于 x
的类型检查信息是否比其签名更多?
简而言之,显式类型注释不是类型签名。
特别是在
let x : [> `Error1 ] = (`Error1 : [ `Error1 ])
x
的类型是 [ `Error1 ]
。
问题的根源是显式类型注释中的统一类型变量可以与具体类型统一。
你的问题的一个更简单的例子是
let f: 'a -> 'a = fun x -> x + 1
此处,'a -> 'a
注释与真实类型 int->int
统一,因此此代码进行了类型检查。如果要使类型变量 'a
通用,则需要通过添加显式通用量化
来更加明确
let f: 'a. 'a -> 'a = fun x -> x + 1
Error: This definition has type int -> int which is less general than
'a. 'a -> 'a
使用隐式行变量的代码也会出现同样的现象:
let x : [> `Error1 ] = (`Error1 : [ `Error1 ])
这个注解不保证x
的类型是[> `Error1]
,只保证可以和[> `Error1]
统一。并且由于类型 [ `Error1 ]
可以与 [> `Error1 ]
统一,因此没有理由引发错误。
和以前一样,如果你想避免这个问题,你需要在注释中明确说明哪些变量被普遍量化:
let x : 'row. ([> `Error1 ] as 'row) = (`Error1 : [ `Error1 ])
Error: This expression has type [ `Error1 ]
but an expression was expected of type [> `Error1 ]
The second variant type is bound to the universal type variable 'a,
it cannot be closed
(这是
考虑以下代码:
版本 1:
let x : [> `Error1 ] = (`Error1 : [> `Error1 ])
let y : [> `Error1 | `Error2 ] = x
版本 2:
let x : [> `Error1 ] = (`Error1 : [ `Error1 ])
let y : [> `Error1 | `Error2 ] = x
版本 1 类型检查,但版本 2 失败(我正在使用 4.09.0 进行编译):
File "test.ml", line 2, characters 33-34:
2 | let y : [> `Error1 | `Error2 ] = x
^
Error: This expression has type [ `Error1 ]
but an expression was expected of type [> `Error1 | `Error2 ]
The first variant type does not allow tag(s) `Error2
注意这个错误出现在y
的定义中,但是x
的签名在这两种情况下是一样的! y
怎么能看到x
的定义里面呢?关于 x
的类型检查信息是否比其签名更多?
简而言之,显式类型注释不是类型签名。 特别是在
let x : [> `Error1 ] = (`Error1 : [ `Error1 ])
x
的类型是 [ `Error1 ]
。
问题的根源是显式类型注释中的统一类型变量可以与具体类型统一。
你的问题的一个更简单的例子是
let f: 'a -> 'a = fun x -> x + 1
此处,'a -> 'a
注释与真实类型 int->int
统一,因此此代码进行了类型检查。如果要使类型变量 'a
通用,则需要通过添加显式通用量化
let f: 'a. 'a -> 'a = fun x -> x + 1
Error: This definition has type int -> int which is less general than 'a. 'a -> 'a
使用隐式行变量的代码也会出现同样的现象:
let x : [> `Error1 ] = (`Error1 : [ `Error1 ])
这个注解不保证x
的类型是[> `Error1]
,只保证可以和[> `Error1]
统一。并且由于类型 [ `Error1 ]
可以与 [> `Error1 ]
统一,因此没有理由引发错误。
和以前一样,如果你想避免这个问题,你需要在注释中明确说明哪些变量被普遍量化:
let x : 'row. ([> `Error1 ] as 'row) = (`Error1 : [ `Error1 ])
Error: This expression has type [ `Error1 ] but an expression was expected of type [> `Error1 ] The second variant type is bound to the universal type variable 'a, it cannot be closed