Дублирование в описании типа OCaml (ml/mli)

Я пытаюсь понять определенную вещь о ocaml модулях и их компиляции:

я вынужден повторно объявить типы, уже объявленные в a .mli в определенном .ml реализации?

Только дать пример:

(* foo.mli *)
type foobar = Bool of bool | Float of float | Int of int

(* foo.ml *)
type baz = foobar option

Это, согласно моему нормальному образу мыслей об интерфейсах/реализациях, должно быть в порядке, но он говорит

Ошибка: Несвязанный конструктор типа foobar

при попытке скомпилировать с

ocamlc -c foo.mli
ocamlc -c foo.ml

Конечно, ошибка исчезает, если я объявляю foobar внутри foo.ml также, но это кажется сложным путем, так как я должен сохранить вещи синхронизировавшими на каждом изменении.

Существует ли способ избежать этого дублирования, или я вынужден повторно объявить типы каждый раз?

Заранее спасибо

32
задан Jack 13 July 2010 в 15:04
поделиться

4 ответа

OCaml пытается заставить вас отделить интерфейс (.mli) от реализации (.ml). В большинстве случаев это хорошо; для значений вы публикуете тип в интерфейсе, а код храните в реализации. Можно сказать, что OCaml обеспечивает определенный уровень абстракции (интерфейсы должны быть опубликованы; никакого кода в интерфейсах).

Для типов, очень часто, реализация является тем же, что и интерфейс: оба утверждают, что тип имеет определенное представление (и, возможно, что объявление типа является генеративным). Здесь не может быть абстракции, потому что у реализатора нет никакой информации о типе, которую он не хотел бы публиковать. (Исключение составляет случай, когда вы объявляете абстрактный тип.)

Один из способов посмотреть на это заключается в том, что интерфейс уже содержит достаточно информации для написания реализации. Учитывая интерфейс type foobar = Bool of bool | Float of float | Int of int, существует только одна возможная реализация. Поэтому не пишите реализацию!

Распространенная идиома - иметь модуль, посвященный объявлениям типов, и сделать его только .mli. Поскольку типы не зависят от значений, этот модуль, как правило, находится в самом начале цепочки зависимостей. Большинство инструментов компиляции хорошо справляются с этим; например, ocamldep сделает все правильно. (Это одно из преимуществ по сравнению с наличием только .ml.)

Ограничение этого подхода возникает, когда вам также нужно несколько определений модулей тут и там. (Типичный пример - определение типа foo, затем OrderedFoo : Map.OrderedType модуль с type t = foo, затем еще одно объявление типа, включающее 'a Map.Make(OrderedFoo).t). Их нельзя поместить в интерфейсные файлы. Иногда допустимо разбить ваши определения на несколько частей, сначала куча типов (types1.mli), затем модуль (mod1.mli и mod1.ml), затем больше типов (types2.mli). В других случаях (например, если определения рекурсивны) приходится жить либо с .ml без .mli, либо с дублированием.

17
ответ дан 27 November 2019 в 20:56
поделиться

Вы можете позволить ocamlc сгенерировать для вас файл mli из файла ml:

ocamlc -i some.ml > some.mli
14
ответ дан 27 November 2019 в 20:56
поделиться

В общем, да, от вас требуется дублировать типы.

Вы можете обойти это, однако, с помощью Camlp4 и расширения синтаксиса pa_macro (пакет findlib: camlp4.macro ). Он определяет, среди прочего, и конструкцию INCLUDE. Вы можете использовать его для выделения общих определений типов в отдельный файл и включения этого файла в файлы .ml и .mli . Однако я не видел, чтобы это было сделано в развернутом проекте OCaml, поэтому я не знаю, можно ли это квалифицировать как рекомендуемую практику, но это возможно.

Однако грамотное программирование чище IMO.

3
ответ дан 27 November 2019 в 20:56
поделиться

Да, вам придется заново объявлять типы. Единственные известные мне способы обойти это -

  • Не использовать .mli файл; просто раскрывать все без интерфейса. Ужасная идея.

  • Использовать инструмент грамотного программирования или другой препроцессор, чтобы избежать дублирования объявлений интерфейсов в единственном истинном источнике. Для больших проектов мы делаем это в моей группе.

Для маленьких проектов мы просто дублируем объявления типов. И ворчим по этому поводу.

18
ответ дан 27 November 2019 в 20:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: