Работа с круговыми зависимостями в OCaml
Я пишу переводчика для экспериментального языка. Три основные конструкции языка - это определения, утверждения и выражения. Определения могут содержать утверждения и выражения, операторы могут содержать определения и выражения, а один вид выражения может содержать утверждения. Я представляю все эти типы соединений, поэтому я могу легко использовать сопоставление шаблонов. В идеале, я хотел бы поместить код для них в разные файлы, но OMake жалуется на проблемы с круговой зависимостью. Насколько я знаю, описания круговых типов в разных модулях не допускаются.
Единственный способ решить эту проблему - определить сразу все три типа:
type defn = ...
and stmt = ...
and expr = ...
Похоже, для этого требуется, чтобы весь код для типов находился в одном файле. Есть ли способ обойти это? Как вы имеете дело с круговыми определениями в вашем коде?
Ответы
Ответ 1
Рекурсивные определения должны появляться в одном файле. Если вы хотите разделить определения, выражения и выражения на отдельные модули, вы можете сделать это с помощью рекурсивных модулей, но они все равно должны появиться в тот же файл. DAG-форматирование зависимостей между файлами является одним из неприятностей OCaml.
Ответ 2
Это легко решить путем параметризации ваших типов по типам, к которым они относятся:
type ('stmt, 'expr) defn = ...
type ('defn, 'expr) stmt = ...
type ('defn, 'stmt) expr = ...
Этот метод называется "развязывание рекурсивного узла" (в отношении гордиев узла) и описан в статье
Ответ 3
Другое часто используемое решение - это абстрагирование типов в интерфейсах. Поскольку типы являются абстрактными в интерфейсах, эти интерфейсы не зависят от рекурсивно. В реализациях вы можете указать типы, и поскольку реализации зависят только от интерфейсов, они также не являются рекурсивными.
Единственная проблема заключается в том, что с этим решением вы больше не сможете сопоставлять шаблоны с этими типами вне их реализации.
Лично, но это, вероятно, вопрос вкуса, мне нравится иметь все типы моей программы, определенные в одном модуле (я думаю, что это помогает в удобочитаемости программы). Итак, это ограничение OCaml для меня не является проблемой.