Polymorphic variants and type signatures

前提是你 提交于 2020-06-16 19:15:30

问题


(This is an extension / distillation of Polymorphic variants and let%bind type error)

Consider the following code:

Version 1:

let x : [> `Error1 ] = (`Error1 : [> `Error1 ])
let y : [> `Error1 | `Error2 ] = x

Version 2:

let x : [> `Error1 ] = (`Error1 : [ `Error1 ])
let y : [> `Error1 | `Error2 ] = x

Version 1 typechecks, but version 2 fails (I'm compiling with 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

Note that this error occurs in the definition of y, but the signature of x is the same in both cases! How is it that y can see inside the definition of x? Is there more typechecking information about x than its signature?


回答1:


In brief, explicit type annotations are not type signatures. In particular, in

let x : [> `Error1 ] = (`Error1 : [ `Error1 ])

the type of x is [ `Error1 ].

The root of the issue is that unification type variables in explicit type annotations can be unified with concrete types.

A simpler instance of your problem is

let f: 'a -> 'a = fun x -> x + 1

Here, the 'a -> 'a annotation is unified with the real type int->int and thus this code typechecks. If you want to make the type variable 'a universal, you need to be more explicit by adding an explicit universal quantification

let f: 'a. 'a -> 'a = fun x -> x + 1
Error: This definition has type int -> int which is less general than
'a. 'a -> 'a

The same phenomenon happens with your code with the implicit row variable:

let x : [> `Error1 ] = (`Error1 : [ `Error1 ])

This annotation does not guarantee that the type of x is [> `Error1] but only that it can be unified with [> `Error1]. And since the type [ `Error1 ] can be unified with [> `Error1 ], there is no reason to raise an error.

As before, if you want to avoid this issue, you need to be explicit about which variables are universally quantified in your annotation:

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


来源:https://stackoverflow.com/questions/62175970/polymorphic-variants-and-type-signatures

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!