☰ OCaml 語言
第 12 章 語言擴展
4 局部抽象類型
(OCaml 3.12 引入,4.03 版本加入簡短語法)
表達式 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 中引入)
(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 節以獲得更詳細的解釋。
方法定義也提供了相同的功能。
Copyright © 2024 Institut National de Recherche en Informatique et en Automatique