改造: $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 とか必要な例は駄目だな、、、