Generics 为什么编译器将两个具有不同泛型类型变量名称的等效签名标识为不同的类型?

Generics 为什么编译器将两个具有不同泛型类型变量名称的等效签名标识为不同的类型?,generics,ocaml,type-inference,type-signature,type-variables,Generics,Ocaml,Type Inference,Type Signature,Type Variables,问题 为什么 val of_bindings : (key * '_a) list -> '_a t val of_bindings : (key * 'a) list -> 'a t 不同的签名 上下文 我有一些地图扩展实现: MAPEXT.ml: module type T = sig include Map.S val of_bindings : (key * 'a) list -> 'a t end module Make (Key :

问题

为什么

val of_bindings : (key * '_a) list -> '_a t
val of_bindings : (key * 'a) list -> 'a t
不同的签名

上下文

我有一些地图扩展实现:

MAPEXT.ml:

module type T = sig
    include Map.S    
    val of_bindings : (key * 'a) list -> 'a t
  end 
module Make (Key : Map.OrderedType)
     : MAPEXT.T with type key = Key.t
module Make (Key : Map.OrderedType) = struct
    include Map.Make (Key)
    let of_bindings =
      let rec of_bindings acc =
        function | (k, v) :: t -> of_bindings (add k v acc) t
                 | []          -> acc in
      of_bindings empty
  end
mapExt.mli:

module type T = sig
    include Map.S    
    val of_bindings : (key * 'a) list -> 'a t
  end 
module Make (Key : Map.OrderedType)
     : MAPEXT.T with type key = Key.t
module Make (Key : Map.OrderedType) = struct
    include Map.Make (Key)
    let of_bindings =
      let rec of_bindings acc =
        function | (k, v) :: t -> of_bindings (add k v acc) t
                 | []          -> acc in
      of_bindings empty
  end
mapExt.ml:

module type T = sig
    include Map.S    
    val of_bindings : (key * 'a) list -> 'a t
  end 
module Make (Key : Map.OrderedType)
     : MAPEXT.T with type key = Key.t
module Make (Key : Map.OrderedType) = struct
    include Map.Make (Key)
    let of_bindings =
      let rec of_bindings acc =
        function | (k, v) :: t -> of_bindings (add k v acc) t
                 | []          -> acc in
      of_bindings empty
  end
编译器给了我一个错误,因为
ocamlopt-c MAPEXT.ml MAPEXT.mli MAPEXT.ml

错误:实现mapExt.ml与接口不匹配 mapExt.cmi: ... 在模块制造位置(钥匙): 值不匹配: val of_bindings:(键*')list->'\u a t 不包括在 val of_binding:(键*'a)list->'a t 文件“mapExt.ml”

我认为泛型类型变量的名称并不重要,只是为了表示不同的类型。但从我现在看到的来看,它们似乎有不同的含义

如何避免这个问题来编译这段代码


相关:

这不仅仅是一个不同的名称(没错,类型变量的名称并不重要)。如果一个类型变量名以
'
序列开头,那么编译器就可以说这个类型变量是弱多态的。简单地说,它根本不是多态的,它表示您的值不是泛型的。基本上,类型变量表示您的值具有一系列类型,例如,
'a list
是一个可能属于一系列类型的值,例如,
int list
string list
,等等。换句话说,类型变量表示无限范围的类型,即,它是所有表示法。弱类型变量正好相反,因为它不在多个类型上范围,而只在一个类型上范围,即,如果您有一个类型为
”的值,则表示存在一个类型
x
(一个且只有一个),因此您的值的类型为
x list
。只是编译器还不知道类型。出于礼貌,编译器给了我们额外的自由度,并且没有给出类型错误

一个类型变量没有被泛化为for all概念,而是坚持exists符号的原因隐藏在OCaml和函数应用程序的易变性中。一般的规则是,如果编译器不能证明一个值计算没有任何可观察的副作用,那么该值就不是广义的,并且所有类型变量都很弱。由于从部分函数应用程序获得的值是任意计算的结果,编译器保守地假设计算可能会产生副作用,并且不会泛化该类型。这称为,它是OCaml类型系统的一个特性。处理它的通常方法是添加所有参数,这样该值就不会由部分应用程序生成,而是成为一个语法值——编译期间计算(确定)的一类值。这种机制的别致名称是

请阅读“通过部分应用程序获得的函数不够多态”以及本手册的以下章节