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

Глава 11 Язык OCaml

11 Выражения модулей (реализации модулей)

  • 11.1 Простые выражения модулей
  • 11.2 Структуры
  • 11.3 Функторы

Выражения модулей — это эквивалент выражений-значений на уровне модулей: они вычисляются в модули, предоставляя тем самым реализации спецификаций, выраженных в типах модулей.

module-expr ::= module-path
∣ struct [ module-items ] end
∣ functor { ( module-name : module-type ) }+ -> module-expr
∣ module-expr ( module-expr )
∣ ( module-expr )
∣ ( module-expr : module-type )
module-items ::= { ;; } ( definition ∣ expr ) { { ;; } ( definition ∣ ;; expr) } { ;; }
module-definition ::= module module-name { ( module-name : module-type ) } [ : module-type ] = module-expr
local-definition ::= external value-name : typexpr = external-declaration
∣ type-definition
∣ exception-definition
∣ class-definition
∣ classtype-definition
∣ module-definition
∣ module type modtype-name = module-type
∣ open module-path
definition ::= let [rec] let-binding { and let-binding }
∣ include module-expr
∣ local-definition

См. также следующие расширения языка: рекурсивные модули, модули первого класса, переопределение в операторах 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 module-name : module-type = module-expr

вместо

module module-name = ( module-expr : module-type ).

Ещё одна производная форма:

module module-name ( name1 : module-type1 ) … ( namen : module-typen ) = module-expr

эквивалентная записи

module module-name = functor ( name1 : module-type1 ) -> … -> module-expr

Определения типов модулей

Определение типа модуля записывается как 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 в расширенном окружении и возвращает полученные модули в качестве результатов. Тип аргумента функтора ничем не ограничен; в частности, функтор может принимать другой функтор в качестве аргумента (функтор «высшего порядка»).

Если результирующее выражение модуля само является функтором,

functor ( name1 : module-type1 ) -> … -> functor ( namen : module-typen ) -> module-expr

можно использовать сокращённую форму

functor ( name1 : module-type1 ) … ( namen : module-typen ) -> module-expr

Применение функтора

Выражение module-expr1 ( module-expr2 ) вычисляет module-expr1 в функтор, а module-expr2 — в модуль, после чего применяет первый ко второму. Тип module-expr2 должен соответствовать типу, ожидаемому для аргументов функтора module-expr1.

« Типы модулей (спецификации модулей)Единицы компиляции »
Copyright © 2026 Национальный институт исследований в области информатики и автоматики

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

Spec-Zone.ru

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