Язык Ocaml поддерживает рекурсию между модулями, но компилятор не поддерживает рекурсию между модулями компиляции. Таким образом, вы не можете иметь A.ml
нуждающимся B.ml
и B.ml
нуждающимся A.ml
. Рефакторинг для удаления рекурсии лучше, если вы можете сделать это легко, но давайте предположим, что вы не можете.
Одним из решений, как объясняет nlucaroni, является объединение обоих модулей в один файл и использование module rec
. Другое решение иногда состоит в том, чтобы превратить один модуль в функтор, например, превратить A
в функтор F
, который принимает аргумент с подписью B
, и скомпилировать сначала файл, определяющий F
, затем B
затем файл, который просто определяет module A = F(B)
.
Ocamlyacc делает вещи более сложными, но вы можете обмануть это! Вы можете написать module A = functor (...) -> struct
в заголовке .mly
и соответствующий end
в нижнем колонтитуле. Однако вам придется переписать сгенерированные .mli
, чтобы добавить module A : functor (...) -> sig
и end
как часть процесса сборки. (Я знаю, что делал это раньше, чтобы решить ту же проблему, что и у вас, хотя я не помню, где, поэтому я не могу привести пример из реальной жизни.)
Еще одна возможность, заслуживающая изучения, - это переключение с Ocamlyacc на Menhir , который является заменой Ocamlyacc (практически не требует переноса, так как синтаксис такой же), с некоторыми полезными функциями, которые могут вам помочь, такими как поддержка параметризованных модулей синтаксического анализа (т. е. функторов).