Мне любопытно понять, почему возникает эта ошибка и как ее лучше всего обойти .
У меня есть пара файлов types.ml
и types.mli
, которые определяют вариантный тип значение
, который может иметь множество различных встроенных типов OCaml. (float, int, list, map, set и т. д.).
Поскольку я должен использовать std-lib вместо этого варианта типа, мне нужно было конкретизировать модуль 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.
Это все, что я нашел до сих пор, но я не понимаю точного значения ..
Заранее благодарю