为什么在OCAML中相互递归模块中的签名要求?
-
13-10-2019 - |
题
当在OCAML中使用相互递归的模块定义时,即使在 .ml
文件。这是一个烦人,我也想从 .mli
, ,当我最终重复两次签名时。 :(!
module rec Client : sig
type ('serv,'cli) t
(* functions ... *)
end = struct
type ('serv,'cli) t =
{ server: ('serv,'cli) Server.t
; (* other members ... *)
}
end
and Server : sig
type ('serv,'cli) t
(* functions ... *)
end = struct
type ('serv,'cli) t =
{ mutable clients: ('serv,'cli) Client.t list
; mutable state: 'serv
}
(* functions again ... *)
end
这是我正在做的事情的粗略近似(Client
类型对象知道 Server
那实例化了它们。 Server
知道他们的 Client
S)。
当然,签名在 .mli
. 。为什么需要这?
(注意:我不是在抱怨,但实际上想知道是否有类型理论或“硬编译器问题”相关的原因。)
解决方案
我的猜测是:为了编译递归模块编译器需要类型注释以实现。在MLI文件(如果您使用的任何类型)中,可以进一步限制或完全隐藏这些模块,因此,对于编译器来说,不明智地期望在MLI WRT解析类型回复中找到有用的类型。
其他提示
据我所知,这是没有办法的。就编译器而言,在很高的水平上,客户端的类型签名是不完整的,直到知道服务器的类型签名,反之亦然。原则上,有一种方法:编译器可以在编译时交叉引用.MLI文件。但是这种方法具有缺点:它混合了编译器和链接器的某些责任,并使模块化编译(无双关语)更加困难。
如果您有兴趣,我建议Xavier Leroy's 原始建议 用于递归模块。
不隶属于 StackOverflow