5. 発端となる"Guarded Recursive Datatype Constructors"(by Hongwei Xi, Chiyan Chen and Gang Chen)や"First-Class Phantom Types” (by James Cheney and Ralf Hinze)などの論文が2003年。
10. 存在型=型パラメータを隠せる Objective Caml version 3.13.0-gadt (2010-10-22) # type t = 'a list;; Error: Unbound type parameter 'a # type t = List : 'a list -> t;; type t = List : 'a list -> t ’ a が存在型
11. 例えばコンビネーターの型 type 'a event = Return of 'a | Join of 'a event event | Choose of 'a event list | Guard of unit -> 'a event | Wrap of ('b -> 'a) * 'b event あれ?書けないぞ。
12. GADTなら大丈夫 type 'a event = Return : 'a -> 'a event | Join : 'a t t -> 'a event | Choose : 'a event list -> ' a event | Guard : (unit -> 'a event) -> 'a event | Wrap : ('b -> 'a) * 'b event -> 'a event やったね!
13. 不変量(お約束)は避けたいね type term = Int of int | String of string | Mul of term * term Mul 構文は本当は Int バリアントにしか許したくないのに、 term 全体を受け取るしかない。
14. GADTなら大丈夫! # type _ term = Int : int -> int term | String : string -> string term | Mul : int term -> int term -> int term 気にしなきゃイケない 不変量(お約束)が減ったよ!
15. 例えば型付きSQLクエリ type column = string (* カラム名 *) type _ term = (* 項。簡略版 *) | Int : int -> int term | String : string -> string term | IntColumn : column -> int term | StringColumn : column -> string term
16. where要素 type compare_op = EQ | GE | LE type 'a where_elem = 'a term * compare_op * 'a term type _ where = | WReturn : 'a where_elem -> 'a where | WOr : ('a where_elem * 'b where) -> ('a * 'b) where | WAnd : ('a where_elem * 'b where) -> ('a * 'b) where
17. select要素とfrom要素 type _ select = | SReturn : 'a term -> 'a select | SCons : ('a term * 'b select) -> ('a * 'b) select type from = | Table : string -> from | Join : from * from -> from
18. 型付きクエリの出来上がり type _ query = Query : 'a select * from * 'b where option -> 'a qeury
19. 実際に作ってみた val sql : (string * int) select * from * (string * int) where option = (SCons (StringColumn "name", SReturn (IntColumn "age")), Table "person", Some (WAnd ((StringColumn "name", EQ, String "ogasawara"), WReturn (IntColumn "age", GE, Int 20))))
20. 型付きクエリを使ってごにょごにょ (* 型で守ってから文字列に変換 *) val to_strng : type s. s query -> string (* 型付きクエリを実行して型付き結果をもらう *) val execute : type s. s query -> db -> s seq 夢が広がるよ!
21. 今日からあなたもGADTer! インストールは簡単! $ svn co http://caml.inria.fr/svn/ocaml/branches/gadts $ cd gadts $ ./configure; make world.opt $ sudo make install