recursion - OCaml:是否可以在单独的文件中定义相互递归的数据结构

标签 recursion module ocaml

我是 OCaml 的初学者。
我想知道如何在单独的文件中定义相互递归的数据类型。

我知道以下程序是合法的。

type t1 = A of int | B of t2
and  t2 = C of float | C of t1

现在,我想定义这个 t1t2在其他文件中以提高可读性(因为单独需要很多 util 函数)。

我也知道,我可以定义t1t2如上所述,通过制作 .mli文件并隐藏实现细节(只需在 type t1 文件中写入 type t2.mli)。

但是,现在我不想隐藏它们。
有谁知道该怎么做?

我希望简单的解决方案(不要使用复杂的或魔术的......)。

最佳答案

在当前的 OCaml 实现中,编译单元依赖图必须是非循环的。更简单地说,编译单元(即不同的文件)不能相互递归地相互引用。

这个限制是一个过度近似,因为它不允许有效的程序,并且它与直觉相矛盾,因为可以在单个编译单元中编写递归模块。这种限制的原因来自于递归模块类型检查的复杂性。递归模块不能作为独立实体进行类型检查,因为它需要递归中涉及的整个模块集。但是 OCaml 单独的编译系统要求每个编译单元都是独立的和可键入的。如果 OCaml 不使用单独的编译(并将程序作为一个整体链接),那么就有可能实现递归单元。

部分解决方案是将独立于相互递归的接口(interface)部分分解并在单独的模块中实现它们。例如,您可以按如下方式定义您的类型:

type 'b a = A of int | B of 'b
type 'a c = C of float | C of 'a
type t1 = t2 a and t2 = t1 c

现在您可以为 'b a 定义接口(interface)的非循环部分。这个接口(interface)对于 'b 类型变量应该是通用的(换句话说,它不应该接触它)。在我们的示例中,很难想象这样的接口(interface),但是,假设示例是合成的,但是对于产品类型,此方法将是有意义的(参见 type 'b a = {a : int; b : 'b } - 您可以实现与 a 字段相关的所有功能)。

作为最后一点,我想说递归模块在实践中很少需要,并且通常表示设计中存在问题。特别是,当需要在单独的模块中移动定义时——这表明没有正确选择抽象。当然,可能的情况是,潜在的问题本质上是复杂的,但这在现实生活中非常罕见。

关于recursion - OCaml:是否可以在单独的文件中定义相互递归的数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42395707/

相关文章:

pattern-matching - OCaml 多态变体 : bind the same name in multiple match patterns

java - 递归地按升序打印整数

php - 递归要求所有文件

具有前端和管理功能的 Magento 模块

ocaml - 在 OCaml 中总结列表的最惯用(或最快)的方法是什么?

syntax-error - 语法错误OCaml

python - 递归函数不返回 True 或 False,但流程正确且有效?

使用递归计算c中单词(字符串)中字母出现的次数

module - 为什么直接绑定(bind) `our &foo` 不起作用,但通过动态查找间接绑定(bind)?

python - Python 2.7 中的 boost 模块?