OCaml中循环依赖的处理

OCaml中循环依赖的处理,ocaml,Ocaml,我正在为一种实验语言写一个口译员。语言的三个主要结构是定义、语句和表达式。定义可以包含语句和表达式,语句可以包含定义和表达式,一种表达式可以包含语句。我使用联合类型表示所有这些类型,因此可以轻松地对它们使用模式匹配。理想情况下,我希望将这些代码放在不同的文件中,但OMake抱怨循环依赖性问题。据我所知,跨模块的循环类型定义是不允许的 我知道解决这个问题的唯一方法是同时定义所有三种类型: type defn = ... and stmt = ... and expr = ... 这似乎要求类型的

我正在为一种实验语言写一个口译员。语言的三个主要结构是定义、语句和表达式。定义可以包含语句和表达式,语句可以包含定义和表达式,一种表达式可以包含语句。我使用联合类型表示所有这些类型,因此可以轻松地对它们使用模式匹配。理想情况下,我希望将这些代码放在不同的文件中,但OMake抱怨循环依赖性问题。据我所知,跨模块的循环类型定义是不允许的

我知道解决这个问题的唯一方法是同时定义所有三种类型:

type defn = ...
and stmt = ...
and expr = ...

这似乎要求类型的所有代码都在同一个文件中。这有什么办法吗?如何处理代码中的循环定义?

递归定义需要出现在同一文件中。如果要将定义、语句和表达式分离到单独的模块中,可以使用,但它们仍需要显示在同一文件中。数据化文件间依赖关系是OCaml的烦恼之一。

通过将类型参数化到它们所引用的类型上,可以轻松解决这一问题:

type ('stmt, 'expr) defn = ...
type ('defn, 'expr) stmt = ...
type ('defn, 'stmt) expr = ...
这种技术被称为“解开递归结”(参考Gordian的结),并在一篇文章中进行了描述

干杯,
Jon Harrop.

另一种常用的解决方案是抽象接口中的类型。因为类型在接口中是抽象的,所以这些接口不是递归依赖的。在实现中,您可以指定类型,并且由于实现仅依赖于接口,因此它们也不是递归的

唯一的问题是,使用此解决方案,您无法在这些类型的实现之外再进行模式匹配


就个人而言,这可能是一个品味的问题,我喜欢在一个模块中定义所有类型的程序(我认为这有助于提高程序的可读性)。因此,OCaml的这种限制对我来说并不是一个真正的问题。

Golang包依赖也是一个DAG tmk,它是一个b*tch…不仅仅是OCaml,指向递归模块的链接似乎被破坏了:(