8.5 Locally abstract types
(Introduced in OCaml 3.12, short syntax added in 4.03)
|
The expression fun(typetypeconstr-name)-> expr introduces atype constructor named typeconstr-name which is considered abstractin the scope of the sub-expression, but then replaced by a fresh typevariable. Note that contrary to what the syntax could suggest, theexpression fun(typetypeconstr-name)-> expr itself does notsuspend the evaluation of expr as a regular abstraction would. Thesyntax has been chosen to fit nicely in the context of functiondeclarations, where it is generally used. It is possible to freely mixregular function parameters with pseudo type parameters, as in:
let f = fun (type t) (foo : t list) -> …
and even use the alternative syntax for declaring functions:
let f (type t) (foo : t list) = …
If several locally abstract types need to be introduced, it is possible to usethe syntaxfun(typetypeconstr-name1 … typeconstr-namen)-> expras syntactic sugar for fun(typetypeconstr-name1)-> … ->fun(type typeconstr-namen)-> expr. For instance,
let f = fun (type t u v) -> fun (foo : (t * u * v) list) -> … let f' (type t u v) (foo : (t * u * v) list) = …
This construction is useful because the type constructors it introducescan be used in places where a type variable is not allowed. Forinstance, one can use it to define an exception in a local modulewithin a polymorphic function.
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)
Here is another example:
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)
It is also extremely useful for first-class modules (seesection 8.6) and generalized algebraic datatypes(GADTs: see section 8.11).
Polymorphic syntax
(Introduced in OCaml 4.00)
|
The (typetypeconstr-name) syntax construction by itself does not makepolymorphic the type variable it introduces, but it can be combinedwith explicit polymorphic annotations where needed.The above rule is provided as syntactic sugar to make this easier:
let rec f : type t1 t2. t1 * t2 list -> t1 = …
is automatically expanded into
let rec f : 't1 't2. 't1 * 't2 list -> 't1 = fun (type t1) (type t2) -> ( … : t1 * t2 list -> t1)
This syntax can be very useful when defining recursive functions involvingGADTs, see the section 8.11 for a more detailed explanation.
The same feature is provided for method definitions.