17

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

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

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

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

4

3 回答 3

16

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

于 2008-08-31T01:00:05.537 回答
14

这很容易通过参数化你的类型来解决它们引用的类型:

type ('stmt, 'expr) defn = ...
type ('defn, 'expr) stmt = ...
type ('defn, 'stmt) expr = ...

这种技术被称为“解开递归结”(参考 Gordian 的结),并在OCaml 期刊文章中进行了描述。

干杯,乔恩·哈罗普。

于 2008-10-19T05:42:25.570 回答
5

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

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

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

于 2012-02-16T20:51:37.457 回答