11.11 Выражения модулей (реализации модулей)
Выражения модулей — это аналог выражений значений на уровне модулей: они вычисляются в модули, предоставляя реализации, выраженные в типах модулей.
|
См. также следующие расширения языка: рекурсивные модули, модули первого класса, переопределение в операторах open, атрибуты, узлы расширения и генерирующие функторы.
11.11.1 Простые выражения модулей
Выражение module-path вычисляется в модуль, связанный с именем module-path.
Выражение ( module-expr ) вычисляется в тот же модуль, что и module-expr.
Выражение ( module-expr : module-type ) проверяет, что тип module-expr является подтипом module-type, то есть, что все компоненты, указанные в module-type, реализованы в module-expr, и их реализация соответствует требованиям, заданным в module-type. Другими словами, он проверяет, что реализация module-expr соответствует спецификации типа module-type. Всё выражение вычисляется в тот же модуль, что и module-expr, за исключением того, что все компоненты, не указанные в module-type, скрыты и больше недоступны.
11.11.2 Структуры
Структуры struct … end представляют собой коллекции определений для имён значений, имён типов, исключений, имён модулей и имён типов модулей. Определения вычисляются в порядке их появления в структуре. Области связываемых имён, создаваемых определениями, распространяются до конца структуры. Вследствие этого определение может ссылаться на имена, привязанные ранее в той же структуре.
Для совместимости с точечными фразами (глава 14), необязательные ;; разрешены после и перед каждым определением в структуре. Эти ;; не имеют семантического значения. Аналогично, expr, предваряемый ;;, разрешён как компонент структуры. Он эквивалентен let _ = expr, то есть expr вычисляется для побочных эффектов, но не связывается ни с каким идентификатором. Если expr является первым компонентом структуры, предшествующее ;; можно опустить.
Определения значений
Определение значения let [rec] let-binding { and let-binding } связывает имена значений аналогично выражению let … in … (см. раздел 11.7.2). Имена значений, появляющиеся в левых частях связываний, связываются с соответствующими значениями в правых частях.
END_OF_DOCUMENT_MARKERОпределение значения external value-name : typexpr = external-declaration реализует value-name как внешнюю функцию, заданную в external-declaration (см. главу 22).
Определения типов
Определение одного или нескольких компонентов типа записывается как 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.11.3 Функторы
Определение функтора
Выражение functor ( module-name : module-type ) -> module-expr вычисляет функтор, который принимает в качестве аргумента модули типа module-type1, связывает module-name с этими модулями, вычисляет module-expr в расширенной среде и возвращает полученные модули как результаты. Никаких ограничений на тип аргумента функтора не накладывается; в частности, функтор может принимать другой функтор в качестве аргумента («функтор высшего порядка»).
Когда выражение результата модуля само является функтором,
можно использовать сокращённую форму
Применение функтора
Выражение выражение-модуля1 ( выражение-модуля2 ) вычисляет выражение-модуля1 в функтор и выражение-модуля2 в модуль, и применяет первый ко второму. Тип выражение-модуля2 должен соответствовать типу, ожидаемому для аргументов функтора выражение-модуля1.
© 1995-2022 INRIA.
https://v2.ocaml.org/releases/5.0/htmlman/modules.html