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