当在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知道他们的 ClientS)。

当然,签名在 .mli. 。为什么需要这?

(注意:我不是在抱怨,但实际上想知道是否有类型理论或“硬编译器问题”相关的原因。)

有帮助吗?

解决方案

我的猜测是:为了编译递归模块编译器需要类型注释以实现。在MLI文件(如果您使用的任何类型)中,可以进一步限制或完全隐藏这些模块,因此,对于编译器来说,不明智地期望在MLI WRT解析类型回复中找到有用的类型。

其他提示

据我所知,这是没有办法的。就编译器而言,在很高的水平上,客户端的类型签名是不完整的,直到知道服务器的类型签名,反之亦然。原则上,有一种方法:编译器可以在编译时交叉引用.MLI文件。但是这种方法具有缺点:它混合了编译器和链接器的某些责任,并使模块化编译(无双关语)更加困难。

如果您有兴趣,我建议Xavier Leroy's 原始建议 用于递归模块。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top