错误:无法安全地评估递归定义模块的定义

2024-04-22

我很想了解为什么会发生此错误以及解决该错误的最佳方法是什么。

我有几个文件types.ml and types.mli它定义了一个变体类型value可以是许多不同的内置 OCaml 类型(float、int、list、map、set 等)。

由于我必须在这个变体类型上使用 std-lib,所以我需要通过函子具体化 Set 模块,以便能够使用value类型通过定义ValueSet module.

决赛.ml文件是这样的:

module rec I :
sig 
  type value =
    Nil
  | Int of int
  | Float of float
  | Complex of Complex.t
  | String of string
  | List of (value list) ref
  | Array of value array
  | Map of (value, value) Hashtbl.t
  | Set of ValueSet.t ref
  | Stack of value Stack.t
  ...

  type t = value 
  val compare : t -> t -> int
end
= struct

  (* same variant type *)

  and string_value v =
    match v with
      (* other cases *)
      | Set l -> sprintf "{%s} : set" (ValueSet.fold (fun i v -> v^(string_value  i)^" ") !l "")
end
and OrderedValue :
sig
    type t = I.value
    val compare : t -> t -> int
end
= struct
    type t = I.value
    let compare = Pervasives.compare
end
and ValueSet : Set.S with type elt = I.value = Set.Make(I)

正如你所看到的,我必须定义ValueSet函子中的模块能够使用该数据类型。当我想在声明中使用该模块时,就会出现问题I。这样我就得到以下错误:

错误:无法安全地评估递归定义模块 I 的定义

为什么会出现这种情况?有什么好的方法可以解决吗?只是想知道,我尝试做的事情的方法是否正确?除此之外,它按预期工作(我可以在其他模块中的操作中使用 ValueSet 类型,但我必须注释中涉及的行types.ml通过编译阶段)。

我尝试删除所有多余的代码并将代码减少到调查此错误所需的必要代码..如果还不够,只需询问:)

编辑:根据 OCaml 参考我们有

目前,编译器要求递归定义的模块标识符之间的所有依赖循环至少经过一个“安全”模块。如果模块包含的所有值定义都具有函数类型 typexpr1 -> typexpr2,则该模块是“安全的”。

这是迄今为止我发现的所有内容,但我不明白确切的含义。

预先感谢


修复明显的错误后,您的示例确实可以编译(使用 OCaml 3.10,但我认为自从 3.07 中引入递归模块以来,这一点没有改变)。希望我下面的解释能够帮助您找到您遗漏的定义中导致代码被拒绝的原因。

以下是一些被接受的示例代码:

module rec Value : sig
  type t =
    Nil
  | Set of ValueSet.t 
  val compare : t -> t -> int
  val nil : t
  (*val f_empty : unit -> t*)
end
= struct
  type t =
    Nil
  | Set of ValueSet.t
  let compare = Pervasives.compare
  let nil = Nil
  (*let f_empty () = Set ValueSet.empty*) 
end
and ValueSet : Set.S with type elt = Value.t = Set.Make(Value)

在表达水平上,该模块Value不依赖于ValueSet。因此编译器生成代码来初始化Value在初始化代码之前Value,一切顺利。

现在尝试注释掉 的定义f_empty.

File "simple.ml", line 11, characters 2-200:
Cannot safely evaluate the definition of the recursively-defined module Value

Now Value确实取决于ValueSet, and ValueSet总是取决于Value因为compare功能。因此它们是相互递归的,并且“安全模块”条件必须适用。

目前,编译器要求所有依赖关系之间的循环 递归定义的模块标识符至少要经过一个“安全”模块。 A 如果模块包含的所有值定义都具有函数类型,则该模块是“安全的”typexpr_1 -> typexpr_2.

Here, ValueSet不安全,因为ValueSet.empty, and Value不安全,因为nil.

“安全模块”条件的原因是递归模块选择的实现技术:

递归模块定义的评估继续进行 通过为所涉及的安全模块构建初始值,绑定所有 (功能)值fun _ -> raise Undefined_recursive_module。定义 然后评估模块表达式,并计算安全的初始值 模块被由此计算的值替换。

如果你注释掉声明nil在签名中Value,你可以留下定义和声明f_empty。那是因为Value现在是一个安全模块:它只包含函数。留下定义就可以了nil在实施中:实施Value不是一个安全模块,但是Value其本身(强制签名的实现)是安全的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

错误:无法安全地评估递归定义模块的定义 的相关文章

  • 如何选择要在 Ruby 中动态包含的模块版本?

    我正在编写一个小型 Rub y 命令行应用程序 它使用fileutils来自文件操作的标准库 根据用户调用应用程序的方式 我想包括FileUtils FileUtils DryRun or FileUtils Verbose Since i
  • 如何使用 RequireJS 构建多个页面

    如何使用RequireJS构建多个页面 就像下面的示例一样 在 app js 中声明每个类是正确的做法吗 有每个 html 文件来声明 我想避免的是当用户到达网站的第一页时加载所有脚本 main js 定义所有外部依赖项 require b
  • 在错误位置寻找模块的代码

    我使用 build dojotoolkit org 我的第一次尝试 创建了一个包含 3 层的多层构建 dojo js dojox js dijit js 每个 js 文件都上传到自己的文件夹中 dojo dojox dijit 当我运行代码
  • DBD::Oracle 安装导致错误

    我想通过 Perl 连接到 Oracle 数据库 为此 我尝试使用以下命令从 CPAN 安装 DBD Oracle root localhost Admin cpan DBD Oracle 在我的 Linux 终端上运行上述命令时 出现以下
  • Python 的“导入”内部是如何工作的?

    当您导入一个模块 然后再次重新导入它时 它会被重新导入 覆盖还是跳过 当您导入模块 a 和 b 并且还在模块 a 中导入模块 b 时 会发生什么 这样做安全吗 例如 如果该模块 b 中有一个实例化的类 您最终会实例化它两次吗 import加
  • 为什么导入的函数“作为”另一个名称保留其原始 __name__ ?

    Here from os path import exists as foo print foo name we get exists 为什么不 foo 哪个属性会给出 foo 您可以查看import foo as bar只是一个任务 你不
  • 使用 OCaml 收集外部命令的输出

    在 OCaml 中调用外部命令并收集其输出的正确方法是什么 在Python中 我可以做这样的事情 os popen cmd read 如何在 OCaml 中获取外部程序的所有输出 或者 更好的是 带有 Lwt 的 OCaml Thanks
  • magento 付款流程..一般如何运作

    有一个问题 我希望这是问的正确地方 不太明白magento 中的付款方式 客户去结账 假设想要以客人身份付款 因此提供地址等 最后找到付款方式 然后我希望客户通过信用卡付款 已经为我选择的网关 银行 安装了模块 那时 我希望用户被重定向到第
  • 如何以轮子格式安装 Python 库?

    我正在寻找有关如何以轮格式安装 Python 库的教程 它看起来并不简单 所以我希望有一个简单的分步教程 说明如何为 CPython 安装名为 requests 的模块 我从以下位置下载的 https pypi python org pyp
  • Ruby:C 类包含模块 M;在 M 中包含模块 N 不会影响 C。什么给出?

    更详细地说 我有一个模块Narf 它为一系列类提供了基本功能 具体来说 我想影响所有继承的类Enumerable So I include Narf in Enumerable Array是一个类 其中包括Enumerable默认情况下 然
  • OCaml:用消息断言

    又是另一个问题 P 我不太确定是否应该将其发布在这里或 OCaml 邮件列表上 但我首先尝试这样做 我喜欢断言语句 然而 我发现如果没有附加消息 错误消息几乎毫无用处 第 XXX 行的断言冲突 很好 但实际上出了什么问题 我认为断言的一个很
  • Rails:如何为 ruby​​ 模块编写测试?

    我想知道如何为混合到几个类中的模块编写单元测试 但不太知道如何去做 我是否通过在包含它们的类的测试文件之一中编写测试来测试实例方法 似乎不正确 或者您可以以某种方式将所包含方法的测试保留在特定于模块的单独文件中吗 同样的问题也适用于类方法
  • 扩展无法启用或安装的问题

    php 7 3 5 你好 我的扩展 ext http 有问题 composer 说我缺少 ext http 即使我在composer json 中写了这个 为什么 这就是这个确切的消息 问题1 您的系统中缺少请求的 PHP 扩展 ext h
  • 如何覆盖 app/code/core/Mage/Core/functions.php 中的 Magento 函数

    我需要重写此文件中的一个函数 应用程序 代码 核心 Mage Core functions php 问题是 它是如此核心 以至于没有与之关联的类 可能是因为 Core 甚至不是一个模块 有谁知道如何在没有类的情况下覆盖文件中的函数 任何帮助
  • OCaml:如何运行包含库的脚本

    我正在按照 Real World OCaml 一书来学习 OCaml 许多程序都需要使用 Jane Street Core 库 当我在顶层使用这个核心库中的函数时 它工作得很好 在那里 我只需使用以下命令来打开 Core 库 use top
  • 如何使用 opam 安装特定版本的 ocaml 编译器

    如何使用 opam 或其他包管理器 安装特定版本的 ocaml 编译器 和兼容包 我快速浏览了 opam 文档 但没有找到相关信息 我需要 ocaml 编译器 最好是本机代码编译器 来构建 unison 一个文件同步软件 我需要使用相同版本
  • 如何在 Perl 脚本中递归查找文件/文件夹?

    我有一个 perl 脚本 我编写了该脚本来递归地搜索 Windows 文件夹中的文件 我输入搜索文本作为 perl 脚本运行时参数 以查找名称中包含此文本的文件 perl脚本如下 use Cwd file1 ARGV 0 res1 glob
  • 将实现拆分到多个文件/模块,并尽可能保持所有内容的私密性

    考虑我的库中的以下代码 pub struct Foo impl Foo fn helper self pub fn do something foo Foo foo helper 我的图书馆的用户应该能够使用Foo and do somet
  • Intellij 12 - 无法重新导入模块

    所以今天我遇到了一个奇怪的问题 我在 IntelliJ 中的一个模块遇到了一些问题 所以我决定尝试将其清除并从新的结账中重建它 我从 项目 窗口中删除了该模块 然后从我的文件系统中删除 重新下载 我回到 Intellij 并尝试导入该模块
  • 使用 ocaml List.fold_left 列表中的最后一个元素

    我可以通过以下代码找到列表的最后一个元素 let last xs a list a let rec aux xs prev match xs with gt prev x ys gt aux ys x in match xs with gt

随机推荐