Spec-Zone.ru › OCaml 5.0

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

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

specification ::= ...
∣ module имя_модуля = путь_к_модулю

В указанном выше определении, находящемся внутри подписи, соответствует только определению модуля, равному путь_к_модулю. И наоборот, псевдоним модуля на уровне типов может соответствовать самому себе или любому надтипу типа модуля, на который он ссылается.

Существуют некоторые ограничения для путь_к_модулю:

  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/5.0/htmlman/modulealias.html

Spec-Zone.ru

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