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

Глава 11 Язык программирования OCaml

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

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

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

выражение-модуля ::= путь-к-модулю
∣ struct [ элементы-модуля ] end
∣ functor ( имя-модуля : тип-модуля ) -> выражение-модуля
∣ выражение-модуля ( выражение-модуля )
∣ ( выражение-модуля )
∣ ( выражение-модуля : тип-модуля )
элементы-модуля ::= { ;; } ( определение ∣ выражение ) { { ;; } ( определение ∣ ;; выражение) } { ;; }
определение ::= let [rec] связывание-let { and связывание-let }
∣ external имя-значения : выражение-типа = декларация-внешнего
∣ определение-типа
∣ определение-исключения
∣ определение-класса
∣ определение-типа-класса
∣ module имя-модуля { ( имя-модуля : тип-модуля ) } [ : тип-модуля ] = выражение-модуля
∣ module type имя-типа-модуля = тип-модуля
∣ open путь-к-модулю
∣ include выражение-модуля

См. также следующие расширения языка: рекурсивные модули, модули первого класса, переопределение в операторах open, атрибуты, узлы расширения и генеративные функторы.

11.1 Простые выражения модулей

Выражение путь-к-модулю вычисляется в модуль, связанный с именем путь-к-модулю.

Выражение ( выражение-модуля ) вычисляется в тот же модуль, что и выражение-модуля.

Выражение ( выражение-модуля : тип-модуля ) проверяет, является ли тип выражение-модуля подтипом тип-модуля, то есть, что все компоненты, указанные в тип-модуля, реализованы в выражение-модуля, и их реализация соответствует требованиям, заданным в тип-модуля. Другими словами, проверяется, соответствует ли реализация выражение-модуля спецификации типа тип-модуля. Целое выражение вычисляется в тот же модуль, что и выражение-модуля, за исключением того, что все компоненты, не указанные в тип-модуля, скрыты и больше недоступны.

11.2 Структуры

Структуры struct … end представляют собой коллекции определений имен значений, имен типов, исключений, имен модулей и имен типов модулей. Определения оцениваются в порядке их появления в структуре. Области связывания, выполняемые определениями, распространяются до конца структуры. Следовательно, определение может ссылаться на имена, связанные предыдущими определениями в той же структуре.

Для совместимости с выражениями верхнего уровня (глава ‍14), необязательные ;; допускаются после и перед каждым определением в структуре. Эти ;; не имеют семантического значения. Аналогично, выражение выражение, предваряемое ;;, допускается как компонент структуры. Оно эквивалентно let _ = выражение, т. е. выражение вычисляется для его побочных эффектов, но не связывается ни с одним идентификатором. Если выражение является первым компонентом структуры, предшествующее ;; можно опустить.

Определения значений

Определение значения let [rec] let-binding { and let-binding } связывает имена значений таким же образом, как выражение let … in … (см. раздел ‍11.7.2). Имена значений, появляющиеся в левой части связываний, связываются с соответствующими значениями в правой части.

Определение значения 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 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.

« Типы модулей (спецификации модулей)Единицы компиляции »
Авторское право © 2024 Institut National de Recherche en Informatique et en Automatique

© 1995-2024 INRIA.
https://ocaml.org/manual/5.2/modules.html

Spec-Zone.ru

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