为什么 OCaml 中的相互递归模块需要签名?

发布于 2024-10-13 02:42:59 字数 757 浏览 4 评论 0原文

在 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类型对象知道实例化它们的ServerServer知道它们的Client

当然,签名在 .mli 中重复。

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

When using mutually recursive module definitions in OCaml, it's necessary to give signatures, even in the .ml file. This is an annoyance where I also want to expose a given interface from the .mli, as I end up repeating the signature twice. :(!

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

This is a rough approximation of what I'm doing (Client type objects know the Server that instantiated them. Servers know their Clients).

Of course, the signatures are repeated in the .mli. Why is this necessary?

(Note: I'm not complaining, but actually want to know if there's a type-theory or "hard compiler problem"-related reason for this.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

金橙橙 2024-10-20 02:42:59

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

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

As far as I know, there is no way around it this. At a very high level, as far as the compiler is concerned, the type signature of Client is incomplete until it knows the type signature of Server, and vice versa. In principle, there is a way around this: the compiler could cross reference your .mli files at compile time. But that approach has disadvantages: it mixes some of the responsibilities of the compiler and the linker, and makes modular compilation (no pun intended) more difficult.

If you're interested, I recommend Xavier Leroy's original proposal for recursive modules.

热血少△年 2024-10-20 02:42:59

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

My guess : in order to compile recursive modules compiler needs type annotations for implementation. In mli file (if you are using any) types of those modules can be further restricted or hidden altogether, so in general case it is not sensible for compiler to expect to find useful types in mli wrt resolving type-recursion.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文