OCaml

オブジェクト指向のML系関数型言語OCaml (Objective Caml) 関連。

最近、Microsoft が .NET Framework に F# として移植 (?) したことで、もしかして火がつくか?! いよいよ、コンパイラ型関数型言語の時代が来るのか?!


OCaml (私が) 入門

他の人の入門講座ではなく、私自身が入門してゆく過程を書こうという唯我独尊なコーナーです。OCaml のコードと同等な Python コードを出来るだけ書いています。

クラスを書こう

関数よりも先にクラスを書いてみます。

   1 class hoge =
   2     object
   3         method get_val = 10
   4     end;;

必ず 10 を返すメソッド get_val を持つクラス hoge を作ったわけです。Python的に書けば

   1 class hoge:
   2     def get_val(self):
   3         return 10

ですね。メソッド get_val の型は、型推論により自動的に int となります。

クラスのインスタンスは

   1 let h = new hoge;;

で作ります。Pythonの h = hoge() に相当します。ここでも、h の型は、型推論により hoge になります。メソッド get_val を呼ぶには # を使用して

   1 h#get_val

です。Pythonなどの h.get_val() ですね。

クラスは関数と同じく引数を取れるようです。C++などのコンストラクタに相当することが出来るみたいです。

   1 class hoge init_val =
   2     object
   3         method get_val = init_val + 10
   4     end;;
   5 let h = new hoge 20;;

とすることで

   1 h#get_val

20 + 1030 になるんですね。

ここでは、init_valinit_val + 10 という式で使われていることから、init_val の型は int と型推論されます。式の中で使わず、

   1 class hoge init_val =
   2     object
   3         method get_val = init_val
   4     end;;

とすると、init_val の型を推論できないといって、エラーになってしまいました。そこで、明示的に型を指定してやります。

   1 class hoge (init_val : int) =
   2     object
   3         method get_val = init_val
   4     end;;

これで正しく、

   1 let h = new hoge 20;;
   2 h#get_val;;

20 が表示されます。

インスタンス変数

OCaml は関数型言語ですが、変数やインスタンス変数もあるようです。これを使ってみる予定です。

まずは、変更できないインスタンス変数です。関数型言語なのでこちらがデフォルトです。

   1 class hoge =
   2     object
   3         val x = 10
   4         method get_x = x
   5     end;;

Pythonには定数がないのですが、こんな感じ

   1 class hoge:
   2     def __init__(self):
   3         self.x = 10
   4     def get_x(self):
   5         return self.x

ジェネリックプログラミング

クラスを使えば、C++のtemplateみたいに、ひとつの関数を別のクラスのインスタンスに適用できます。

   1 class hoge =
   2     object
   3         method get_val = 10
   4     end;;
   5 class fuga =
   6    object
   7         method get_val = 20
   8    end;;
   9 let h = new hoge;;
  10 let f = new fuga;;

としておきます。そして、関数を一つ作っておきます。

   1 let func x = x#get_val;;

この関数は引数 x のメソッド get_val を呼び出すだけです。この関数には、hoge のインスタンスでも、fuga のインスタンスでも渡せます。

   1 func h;; (* 結果は 10 *)
   2 func f;; (* 結果は 20 *)

C++ (やD言語) のtemplateと同じように使えるわけです。C# や Java の generics と違って、インターフェイスを用いずとも、引数のメソッドを呼べるようになっています。

では、このときの x の型、というか、func の型はどうなっているのかな? と見てみると…

val func : < get_val : 'a; .. > -> 'a = <fun>

だそうです。これは、

ってことのようです。'a ってのは、単相型ってやつかな? 上みたいに h を引数として渡した場合、h#get_valint 型なので、'aint になるみたいです。

うへぇ。型推論すげえなあ。

継承

となると、あとは継承かな。

wiredBeep/topics/Programming/OCaml (last edited 2008-01-28 13:28:26 by beeplex)