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

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

3 Типы с ограниченным доступом

  • 3.1 Типы вариантов и записей с ограниченным доступом
  • 3.2 Сокращения типов с ограниченным доступом
  • 3.3 Типы строк с ограниченным доступом

Объявления типов с ограниченным доступом в сигнатурах модулей, в форме type t = private ..., позволяют библиотекам раскрывать некоторые, но не все аспекты реализации типа для клиентов библиотеки. В этом отношении они занимают среднее положение между объявлениями абстрактных типов, где никакая информация о реализации типа не раскрывается, и определениями типов данных и сокращениями типов, где все аспекты реализации типа публикуются. Объявления типов с ограниченным доступом бывают трех видов: для типов вариантов и записей (раздел ‍12.3.1), для сокращений типов (раздел ‍12.3.2) и для типов строк (раздел ‍12.3.3).

3.1 Типы вариантов и записей с ограниченным доступом

(Введено в Objective Caml 3.07)

type-representation ::= ...
∣ = private [ | ] constr-decl { | constr-decl }
∣ = private record-decl

Значения типа варианта или записи, объявленного как private, могут быть деструктурированы обычным образом в шаблонах сопоставления или с помощью записи expr . field для доступа к полям записей. Однако значения этих типов не могут быть построены напрямую с помощью применения конструктора или создания записи. Кроме того, не разрешено присваивание в изменяемом поле типа записи с ограниченным доступом.

Типичное использование типов с ограниченным доступом находится в экспортной сигнатуре модуля, чтобы гарантировать, что создание значений типа с ограниченным доступом всегда происходит через функции, предоставляемые модулем, при этом все еще позволяя сопоставление шаблонов за пределами определяющего модуля. Например:

module M : sig
  type t = private A | B of int
  val a : t
  val b : int -> t
end = struct
  type t = A | B of int
  let a = A
  let b n = assert (n > 0); B n
end

Здесь объявление private гарантирует, что в любом значении типа M.t аргумент конструктора B всегда является положительным целым числом.

Что касается вариативности их параметров, типы с ограниченным доступом обрабатываются как абстрактные типы. То есть, если у типа с ограниченным доступом есть параметры, их вариативность определяется явно с помощью префикса ‘+’ или ‘-’; в противном случае вариативность неизменна.

3.2 Сокращения типов с ограниченным доступом

(Введено в Objective Caml 3.11)

type-equation ::= ...
∣ = private typexpr

В отличие от обычного сокращения типа, сокращение типа с ограниченным доступом объявляет тип, который отличается от типа его реализации typexpr. Однако преобразования из типа в typexpr разрешены. Более того, компилятор «знает» тип реализации и может использовать эти знания для выполнения оптимизации, ориентированной на тип.

В следующем примере используется сокращение типа с ограниченным доступом для определения модуля неотрицательных целых чисел:

module N : sig
  type t = private int
  val of_int: int -> t
  val to_int: t -> int
end = struct
  type t = int
  let of_int n = assert (n >= 0); n
  let to_int n = n
end

Тип N.t несовместим с int, гарантируя, что неотрицательные целые числа и обычные целые числа не смешиваются. Однако, если x имеет тип N.t, преобразование (x :> int) является допустимым и возвращает базовое целое число, так же как и N.to_int x. Также поддерживаются глубокие преобразования: если l имеет тип N.t list, преобразование (l :> int list) возвращает список базовых целых чисел, так же как List.map N.to_int l, но без копирования списка l.

Обратите внимание, что преобразование ( expr :> typexpr ) — это сокращенная форма и будет работать только в случае наличия сокращений типов с ограниченным доступом, если ни тип expr, ни typexpr не содержат переменных типа. Если они есть, необходимо использовать полную форму ( expr : typexpr1 :> typexpr2 ), где typexpr1 — ожидаемый тип expr. В конкретных примерах это будет (x : N.t :> int) и (l : N.t list :> int list).

3.3 Типы строк с ограниченным доступом

(Введено в Objective Caml 3.09)

type-equation ::= ...
∣ = private typexpr

Типы строк с ограниченным доступом — это сокращения типов, где часть структуры типа остается абстрактной. В частности, typexpr в вышеприведенном случае должен обозначать тип объекта или полиморфный тип варианта с некоторыми возможностями уточнения. Если объявление с ограниченным доступом используется в интерфейсе, соответствующая реализация может предоставить либо базовую реализацию, либо уточненный тип с ограниченным доступом.

module M : sig type c = private < x : int; .. > val o : c end =
struct
  class c = object method x = 3 method y = 2 end
  let o = new c
end

Это объявление делает больше, чем скрытие метода y, оно также делает тип c несовместимым с любым другим закрытым типом объекта, что означает, что только o будет типа c. В этом отношении он ведет себя аналогично типам записей с ограниченным доступом. Но типы строк с ограниченным доступом более гибкие в отношении постепенного уточнения. Эта функция может использоваться в сочетании с функторами.

module F(X : sig type c = private < x : int; .. > end) =
struct
  let get_x (o : X.c) = o#x
end
module G(X : sig type c = private < x : int; y : int; .. > end) =
struct
  include F(X)
  let get_y (o : X.c) = o#y
end

Тип полиморфного варианта [t], например

type t = [ `A of int | `B of bool ]

может быть уточнен двумя способами. Определение [u] может добавить новые поля к [t], и объявление

type u = private [> t]

сохранит эти новые поля абстрактными. Создание значений типа [u] возможно с использованием известных вариантов [t], но любой шаблон сопоставления потребует обработчика по умолчанию для потенциальных дополнительных полей. Двойственно, объявление [u] может ограничить поля [t] посредством абстракции: объявление

type v = private [< t > `A]

соответствует типам вариантов с ограниченным доступом. Нельзя создать значение типа с ограниченным доступом [v], кроме как с использованием явно перечисленных конструкторов, (`A n) в этом примере; однако при сопоставлении шаблонов с [v] необходимо учитывать, что любой конструктор из [t] может быть присутствовать.

Аналогично абстрактным типам, вариативность параметров типа не выводится и должна быть указана явно.

« Рекурсивные модулиЛокально абстрактные типы »
Авторские права © 2024 Institut National de Recherche en Informatique et en Automatique

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

Spec-Zone.ru

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