我很想知道为什么会发生这个错误,这是解决它的最佳方法。
我有几个文件types.ml
,types.mli
它们定义了一个变体类型value
,它可以是许多不同的内置 OCaml 类型(float、int、list、map、set 等)。
由于我必须在这个变体类型上使用标准库,我需要通过函子具体化 Set 模块,以便能够value
通过定义ValueSet
模块来使用类型集。
最终.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,则该模块是“安全的”。
这是我到目前为止发现的所有内容,但我不明白确切的含义..
预先感谢