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

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

4 Локально абстрактные типы

(Введены в OCaml 3.12, сокращённый синтаксис добавлен в 4.03)

параметр ::= ...
∣ ( type { имя_типа }+ )

Выражение fun ( type имя_типа ) -> выражение вводит конструктор типа с именем имя_типа, который считается абстрактным в области подвыражения, но затем заменяется свежей переменной типа. Обратите внимание, что, вопреки тому, что может подразумевать синтаксис, само выражение fun ( type имя_типа ) -> выражение не приостанавливает вычисление выражения так, как это делала бы обычная абстракция. Синтаксис был выбран для удобной интеграции в контексте объявлений функций, где он обычно используется. Можно свободно смешивать обычные параметры функции с псевдопараметрами типа, как в примере:

let f = fun (type t) (foo : t list) -> …

и даже использовать альтернативный синтаксис для объявления функций:

let f (type t) (foo : t list) = …

Если необходимо ввести несколько локально абстрактных типов, можно использовать синтаксис fun ( type имя_типа1 … имя_типаn ) -> выражение в качестве синтаксического сахара для fun ( type имя_типа1 ) -> … -> fun ( type имя_типаn ) -> выражение. Например,

let f = fun (type t u v) -> fun (foo : (t * u * v) list) -> …
let f' (type t u v) (foo : (t * u * v) list) = …

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

let f (type t) () =
  let module M = struct exception E of t end in
  (fun x -> M.E x), (function M.E x -> Some x | _ -> None)

Вот ещё один пример:

let sort_uniq (type s) (cmp : s -> s -> int) =
  let module S = Set.Make(struct type t = s let compare = cmp end) in
  fun l ->
    S.elements (List.fold_right S.add l S.empty)

Это также чрезвычайно полезно для модулей первого класса (см. раздел ‍12.5) и обобщённых алгебраических типов данных (GADTs: см. раздел ‍12.10).

Полиморфный синтаксис

(Введён в OCaml 4.00)

связывание_let ::= ...
∣ имя_переменной : type { имя_типа }+ . выражение_типа = выражение
поле_класса ::= ...
∣ метод [private] имя_метода : type { имя_типа }+ . выражение_типа = выражение
∣ метод! [private] имя_метода : type { имя_типа }+ . выражение_типа = выражение

Конструкция (type имя_типа) сама по себе не делает вводимую ею переменную типа полиморфной, но её можно комбинировать с явными полиморфными аннотациями по мере необходимости. Приведённое выше правило дано в качестве синтаксического сахара для упрощения этого:

let rec f : type t1 t2. t1 * t2 list -> t1 = …

автоматически расширяется до

let rec f : 't1 't2. 't1 * 't2 list -> 't1 =
  fun (type t1) (type t2) -> ( … : t1 * t2 list -> t1)

Этот синтаксис может быть очень полезен при определении рекурсивных функций, включающих GADTs, см. раздел ‍12.10 для более подробного объяснения.

Такая же возможность предоставляется для определений методов.

« Секретные типыМодули первого класса »
Авторское право © 2024 Institut National de Recherche en Informatique et en Automatique

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

Spec-Zone.ru

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