Ocaml 强制类型缩写记录

Ocaml 强制类型缩写记录,ocaml,record,coercion,Ocaml,Record,Coercion,为什么我不能强制OCaml中的记录类型?像int这样的基本类型可以正常工作 下面是一个示例,其中我构造了一个基本模块M,该模块包含在模块a中M.t是A中指定的类型。只要M.t是int,我就可以做A.t':>M.t。当我将其更改为{I:int}时,编译器会说它不是子类型。我猜这有一个非常具体的原因 module M = struct type t = {i : int} let make () = {i = 10} end module A : sig include module

为什么我不能强制OCaml中的记录类型?像
int
这样的基本类型可以正常工作

下面是一个示例,其中我构造了一个基本模块
M
,该模块包含在模块
a
M.t
A
中指定的类型。只要
M.t
int
,我就可以做
A.t':>M.t
。当我将其更改为
{I:int}
时,编译器会说它不是子类型。我猜这有一个非常具体的原因

module M = struct
  type t = {i : int}
  let make () = {i = 10}
end

module A : sig
  include module type of M
  type t' = private t
  val make : unit -> t'
end = struct
  include M
  type t' = t
end
在顶层:

(A.make() :> M.t);;
Error: Type A.t' is not a subtype of M.t 

这是因为
A.t'
M.t
没有关系,因为
include
没有“保留”相等性,它只是字面上复制模块结构(或签名)并将其内联(作为新的类型和值)。因此类型
M.t
A.t
没有任何关系,因此与
A.t'
没有任何关系(不同的记录类型没有定义结构子类型,比如说对象或模块)。 明显的修正是
类型t'=private M.t

更新


上面的说法似乎不完全正确,因为签名中的
type t'=private M.t
,以及实现中的
include M type t'=t
,所以
include M
保留了平等性(否则它无法匹配签名
type t'=private M.t
),与复制粘贴不同,将
M
的内容替换为
include M
。但这“显然”不适用于创建新类型的
包含模块类型的

另一个修复方法是明确声明,当包含模块类型时,您希望类型相等:
包含类型为t=M.t的M模块类型。您知道为什么这对于记录类型是必需的,而对于基本类型(如
int
)则不是必需的吗?如果将t更改为
type t=int
,则上述代码将起作用。因为在
type t=int
type t'=int
中,
t
t'
是现有类型的别名(类型缩写),可以互换使用。但是
typet={x:int}
typet'={x:int}
——这是两种新类型,根本不相关。