Глава 12. Расширения языка
4 Локально абстрактные типы
(Добавлено в OCaml 3.12, краткий синтаксис появился в 4.03)
|
Выражение fun ( type typeconstr-name ) -> expr вводит конструктор типа с именем typeconstr-name, который считается абстрактным в области видимости подвыражения, но затем заменяется новой переменной типа. Обратите внимание: вопреки тому, что может подразумевать синтаксис, само выражение fun ( type typeconstr-name ) -> expr не откладывает вычисление expr, как это делала бы обычная абстракция. Синтаксис выбран так, чтобы удобно использовать его в объявлениях функций, где он применяется чаще всего. Обычные параметры функции можно свободно сочетать с псевдопараметрами типа, например:
let f = fun (type t) (foo : t list) -> …
и даже использовать альтернативный синтаксис объявления функций:
let f (type t) (foo : t list) = …
Если необходимо ввести несколько локально абстрактных типов, можно использовать синтаксис fun ( type typeconstr-name1 … typeconstr-namen ) -> expr как синтаксический сахар для fun ( type typeconstr-name1 ) -> … -> fun ( type typeconstr-namen ) -> expr. Например:
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) и обобщённых алгебраических типов данных (GADT; см. раздел 12.10).
Полиморфный синтаксис
(Добавлено в OCaml 4.00)
|
Синтаксическая конструкция (type typeconstr-name) сама по себе не делает введённую ею переменную типа полиморфной, но при необходимости её можно сочетать с явными полиморфными аннотациями. Приведённое выше правило добавлено как синтаксический сахар, упрощающий эту задачу:
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)
Этот синтаксис может быть очень полезен при определении рекурсивных функций с GADT; более подробное объяснение см. в разделе 12.10.
Та же возможность предусмотрена для определений методов.
© 1995-2026 INRIA.
https://ocaml.org/manual/5.5/locallyabstract.html