Spec-Zone.ru › OCaml
☰Язык OCaml
  • Язык OCaml
  • Расширения языка

Глава 12. Расширения языка

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.

« Подстановка внутри сигнатурыПереопределение в инструкциях open »
Copyright © 2026 Национальный институт исследований в области информатики и автоматики

© 1995-2026 INRIA.
https://ocaml.org/manual/5.5/modulealias.html

Spec-Zone.ru

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