9

在 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实例化它们的对象。sServer知道它们Client的 s)。

当然,签名在.mli. 为什么这是必要的?

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

4

2 回答 2

7

据我所知,没有办法解决这个问题。在非常高的层次上,就编译器而言,Client 的类型签名是不完整的,直到它知道 Server 的类型签名,反之亦然。原则上,有一种解决方法:编译器可以在编译时交叉引用您的 .mli 文件。但是这种方法有缺点:它混合了编译器和链接器的一些职责,并且使模块化编译(不是双关语)更加困难。

如果你有兴趣,我推荐 Xavier Leroy 对递归模块的原始提案

于 2011-01-20T05:16:14.587 回答
4

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

于 2011-01-20T08:32:34.273 回答