Spec-Zone.ru › OCaml 4.14

10.8 Типовые псевдонимы модулей

(Введено в OCaml 4.02)

specification ::= ...
∣ module module-name = module-path

Вышеприведенное описание внутри сигнатуры соответствует только определению модуля, равному module-path. И наоборот, типовой псевдоним модуля может совпадать с самим собой или с любым типом-супертипом типа модуля, на который он ссылается.

Существуют определенные ограничения на module-path:

  1. он должен иметь вид M0.M1...Mn (т.е. без применений функторов);
  2. внутри тела функтора M0 не должен быть одним из параметров функтора;
  3. внутри рекурсивного определения модуля M0 не должен быть одним из рекурсивно определенных модулей.

Такие спецификации также выводятся. А именно, когда P — путь, удовлетворяющий приведенным выше ограничениям,

module N = P

имеет тип

module N = P

Типовые псевдонимы модулей используются при проверке равенства путей модулей. То есть, в контексте, где имя модуля N известно как псевдоним для P, не только эти два пути модулей считаются равными, но также F(N) и F(P) распознаются как равные. В режиме компиляции по умолчанию это единственное отличие от предыдущего подхода к псевдонимам модулей, у которых просто тот же тип модуля, что и у модуля, на который они ссылаются.

Когда включён флаг компилятора -no-alias-deps, типовые псевдонимы модулей также используются для избежания введения зависимостей между единицами компиляции. А именно, псевдоним модуля, ссылающийся на модуль внутри другой единицы компиляции, не создаёт зависимость при компоновке, пока он не дереференцируется; он всё же вводит зависимость при компиляции, если нужно прочитать интерфейс, т.е. если модуль является подмодулем единицы компиляции или если ссылаются на какие-либо составляющие типа. Кроме того, обращение к псевдониму модуля создаёт зависимость при компоновке от единицы компиляции, содержащей модуль, на который ссылается псевдоним, а не от единицы компиляции, содержащей сам псевдоним. Обратите внимание, что эти различия в поведении при компоновке могут быть несовместимы с предыдущим поведением, так как некоторые единицы компиляции могут не извлекаться из библиотек, и их побочные эффекты игнорируются.

Эти ослабленные зависимости позволяют использовать псевдонимы модулей вместо механизма -pack. Предположим, у вас есть библиотека Mylib, состоящая из модулей A и B. Используя -pack, нужно было бы выполнить команду

ocamlc -pack a.cmo b.cmo -o mylib.cmo

в результате чего получилась бы единица компиляции Mylib, физически содержащая A и B в качестве подмодулей и без зависимостей от соответствующих единиц компиляции. Вот конкретный пример альтернативного подхода:

  1. Переименовать файлы, содержащие A и B, в Mylib__A и Mylib__B.
  2. Создать интерфейс для упаковки Mylib.ml, содержащий следующие строки.
    module A = Mylib__A
    module B = Mylib__B
    
  3. Скомпилировать Mylib.ml с помощью -no-alias-deps, а другие файлы — с помощью -no-alias-deps и -open Mylib (последнее эквивалентно добавлению строки open! Mylib в начало каждого файла).
    ocamlc -c -no-alias-deps Mylib.ml
    ocamlc -c -no-alias-deps -open Mylib Mylib__*.mli Mylib__*.ml
    
  4. Наконец, создайте библиотеку, содержащую все единицы компиляции, и экспортируйте все скомпилированные интерфейсы.
    ocamlc -a Mylib*.cmo -o Mylib.cma
    

Этот подход позволяет напрямую получать доступ к A и B внутри библиотеки и как Mylib.A и Mylib.B снаружи. У него также есть преимущество, что Mylib больше не монолитна: если вы используете Mylib.A, будет подключена только Mylib__A, а не Mylib__B.

Обратите внимание на использование двойных подчеркиваний в Mylib__A и Mylib__B. Это было сделано намеренно; компилятор использует следующий эвристический подход при печати путей: дан путь Lib__fooBar, если Lib.FooBar существует и является псевдонимом для Lib__fooBar, то компилятор всегда будет отображать Lib.FooBar, а не Lib__fooBar. Таким образом, длинные имена Mylib__ остаются скрытыми, а все, что видит пользователь, — это более удобные имена с точкой. Именно так компилируется стандартная библиотека OCaml.

© 1995-2022 INRIA.
https://v2.ocaml.org/releases/4.14/htmlman/modulealias.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API