Глава 11 Язык OCaml
11 Выражения модулей (реализации модулей)
Выражения модулей — это эквивалент выражений-значений на уровне модулей: они вычисляются в модули, предоставляя тем самым реализации спецификаций, выраженных в типах модулей.
|
См. также следующие расширения языка: рекурсивные модули, модули первого класса, переопределение в операторах open, атрибуты, узлы расширения и порождающие функторы.
11.1 Простые выражения модулей
Выражение module-path вычисляется в модуль, связанный с именем module-path.
Выражение ( module-expr ) вычисляется в тот же модуль, что и module-expr.
Выражение ( module-expr : module-type ) проверяет, является ли тип module-expr подтипом module-type, то есть реализованы ли в module-expr все компоненты, указанные в module-type, и удовлетворяет ли их реализация требованиям, заданным в module-type. Иными словами, проверяется, соответствует ли реализация module-expr спецификации типа module-type. Всё выражение вычисляется в тот же модуль, что и module-expr, за исключением того, что все компоненты, не указанные в module-type, скрываются и становятся недоступны.
11.2 Структуры
Структуры struct … end представляют собой наборы определений имён значений, имён типов, исключений, имён модулей и имён типов модулей. Определения вычисляются в том порядке, в котором они указаны в структуре. Области видимости привязок, создаваемых определениями, продолжаются до конца структуры. Следовательно, определение может ссылаться на имена, связанные предыдущими определениями в той же структуре.
Для совместимости с фразами верхнего уровня (глава 14) необязательные ;; допускаются после и перед каждым определением в структуре. Эти ;; не имеют семантического значения. Аналогично, выражение expr, которому предшествует ;;, разрешено в качестве компонента структуры. Оно эквивалентно let _ = expr, то есть expr вычисляется ради побочных эффектов, но не связывается ни с одним идентификатором. Если expr является первым компонентом структуры, предшествующий ему ;; можно опустить.
Определения значений
Определение значения let [rec] let-binding { and let-binding } связывает имена значений так же, как выражение let … in … (см. раздел 11.7.2). Имена значений, стоящие в левых частях связок, связываются с соответствующими значениями в правых частях.
Определение значения external value-name : typexpr = external-declaration реализует value-name как внешнюю функцию, указанную в external-declaration (см. главу 23).
Определения типов
Определение одного или нескольких компонентов типа записывается как type typedef { and typedef } и состоит из последовательности взаимно рекурсивных определений имён типов.
Определения исключений
Исключения определяются с помощью синтаксиса exception constr-decl или exception constr-name = constr.
Определения классов
Определение одного или нескольких классов записывается как class class-binding { and class-binding } и состоит из последовательности взаимно рекурсивных определений имён классов. Определения классов подробнее описаны в разделе 11.9.3.
Определения типов классов
Определение одного или нескольких классов записывается как class type classtype-def { and classtype-def } и состоит из последовательности взаимно рекурсивных определений имён типов классов. Определения типов классов подробнее описаны в разделе 11.9.5.
Определения модулей
Основная форма определения компонента-модуля — module module-name = module-expr: она вычисляет module-expr и связывает результат с именем module-name.
Можно написать
вместо
Ещё одна производная форма:
эквивалентная записи
Определения типов модулей
Определение типа модуля записывается как module type modtype-name = module-type. Оно связывает имя modtype-name с типом модуля, обозначенным выражением module-type.
Открытие пути к модулю
Выражение open module-path в структуре не определяет компоненты и не создаёт привязок. Оно лишь влияет на разбор следующих элементов структуры, позволяя ссылаться на компоненты модуля, обозначенного module-path, по их простым именам name, а не через доступ по пути module-path . name. Область действия open заканчивается в конце выражения структуры.
Включение компонентов другой структуры
Выражение include module-expr в структуре повторно экспортирует в текущей структуре все определения структуры, обозначенной module-expr. Например, если определить модуль S следующим образом
module S = struct type t = int let x = 2 end
то определение модуля B следующим образом
module B = struct include S let y = (x + 1 : t) end
эквивалентно его определению следующим образом
module B = struct type t = S.t let x = S.x let y = (x + 1 : t) end
Различие между open и include состоит в том, что open лишь предоставляет краткие имена для компонентов открытой структуры, не определяя компонентов текущей структуры, тогда как include также добавляет определения компонентов включённой структуры.
11.3 Функторы
Определение функтора
Выражение functor ( module-name : module-type ) -> module-expr вычисляется в функтор, который принимает в качестве аргументов модули типа module-type1, связывает module-name с этими модулями, вычисляет module-expr в расширенном окружении и возвращает полученные модули в качестве результатов. Тип аргумента функтора ничем не ограничен; в частности, функтор может принимать другой функтор в качестве аргумента (функтор «высшего порядка»).
Если результирующее выражение модуля само является функтором,
можно использовать сокращённую форму
Применение функтора
Выражение module-expr1 ( module-expr2 ) вычисляет module-expr1 в функтор, а module-expr2 — в модуль, после чего применяет первый ко второму. Тип module-expr2 должен соответствовать типу, ожидаемому для аргументов функтора module-expr1.
© 1995-2026 INRIA.
https://ocaml.org/manual/5.5/modules.html