改造: $Caml で home made overloading
alpha1 が出来ました: http://jun.furuse.info/hacks/gcaml
- backtrack して overload resolution を行います。ほとんど Haskell type class と同じ。
- overlapping instance とか fun deps とか、そんな面白いものはありません
- resolution 上限が無いので変な定義を書くと型推論で無限ループします
こんな風に使います:
(* type class declaration *) module Sum_class = struct type 'a t = 'a -> int let sum $:d = d end (* instance for int, whose type is int Sum_class.t *) module Sum_int = struct let int : int Sum_class.t = fun x -> x end (* instance for list, whose type is $:'a Sum_class.t -> 'a list Sum_class.t *) module Sum_list : sig val list : $:'a Sum_class.t -> 'a list Sum_class.t end = struct let rec list = function | [] -> 0 | x :: xs -> Sum_class.sum x + list xs end (* put them into one module in order to make the overload resolution work correctly *) module Sum : sig type 'a t (* it must be abstract! *) val sum : $:'a t -> 'a -> int (* overloaded sum *) (* instances must have types with t *) val int : int t val list : $:'a t -> 'a list t end = struct include Sum_class include Sum_int include Sum_list end let _ = assert (Sum.sum [[1]; [2; 3]; [4; 5; 6]] = 21);;
最後の仕上げにいちいち signature を全書きするのが面倒です。なんかいい方法があると良いのですが。
これからはしばらくいろんな type class の例を書いてみて使い勝手を調べて見ようと思います。fun deps とか必要な例は駄目だな、、、