* * *
* *"> *
* * *
Akihito Nagata's Page
|
|
TupleとListとポリモーフィズムrakuda
Ocamlには多くの組み込みデータ型があるが、そのうち比較的簡単なtupleとlistをここで扱う。さらにMLで一番楽しいポリモーフィズムもここで解説する。

ポリモーフィズム

まずポリモーフィズムの例として、恒等関数を定義する。
# let id x = x;;
val id : 'a -> 'a = <fun>
すると、型に"'a"が現れる。これは"どの型でもいい"という意味を表す。よってこの関数はどんな引数も受け付ける。
# id 1;;
- : int = 1
# id "hello";;
- : string = "hello"
一つめの例では引数が1なので"'a"とintがunifyされる。idの返り値の型も"'a"であるので、"id 1"自体の型はintであることがわかる。
このように型にパラメータとして変数を持てるようなポリモーフィズムをparametric polymorphismという。

他の言語と比べてみると

ポリモーフィズムはMLの強力さの一つである。C言語のようにポリモーフィズムのない言語では先の恒等関数は
int int_id(int i){
   return i;
}

char *string_id(char *s){
   return s;
}
のように書かなくてはならない。もしくはオーバーロードを用いて、
int id(int i){
   return i;
}

char *id(char *s){
   return s;
}
のように書く。オーバーローディングはadhocポリモーフィズムとも呼ばれる。
MLにはオーバーローディングはない(オーバーロードしようとすると再定義になる。)。理由としてはMLは型を明示的に書かず推論を行うが、推論とオーバーローディングが重なると推論できない場合が生じる。また、オーバーローディングを許すとどの関数が呼ばれているのかプログラムを読むときにわかりにくいからである。

Tuples

tuple(タプル=組)は順序つきの値の組合わせを作り出す。
tupleはカンマで区切られた値のシーケンスで表現される。
# let p = 1, "Hello";;
val p : int * string = 1, "Hello"
上の例は1と"Hello"の組を作り出し、その型は int * string ということを示している(型のシンタックスではtupleの区切りは"*")。
tupleの中の値を取出すにはパターンマッチングを用いる。
# let p = 1, "Hello";;
val p : int * string = 1, "Hello"
# let x, y = p;;      (* pのそれぞれを取出し、x、yに入れる *)
val x : int = 1
val y : string = "Hello"
# let fst (x, _) = x;;(* 一つめの要素を取出す関数、組み込みなので定義しなくても使える。*)
val fst : 'a * 'b -> 'a = <fun>
# fst p;;             (* 最初の要素である1が取出される *)
- : int = 1
tupleの評価は同時に行われる。値を入れ替えたいときには次のように書く。
# let x,y = y,x;;
val x : string = "Hello"
val y : int = 1
tupleは各要素に名前がつけられないので項目の少ない座標などを表現する場合に適している。

Lists

リストも同様に値の列を作り出したいときに使われる。ただし、Ocamlではリストの各要素の型は等しくなければならない。
リストを作るには"["と"]"でくくる。
# [1 ; 2 ; 3];;
- : int list = [1; 2; 3]
また"[]"は空リストを表し、"x::y"はconsを表す。よって上のリストは下のようにも書ける。
# 1 :: 2 :: 3 :: [];;
- : int list = [1; 2; 3]
リストの要素を取出すときもパターンマッチングを用いる。
以下はリストの順序を逆にする例と、リストの各要素に関数を適用する例である。
# let rec sum lst = (* 要素の和を求める(int用)関数 *)
  match lst with
  [] -> 0
  | hd::tl -> hd + sum tl;; 
val sum : int list -> int = 
# sum [ 1; 2; 3; 4];;
- : int = 10
# let rec map f lst = (* 各要素に関数を適用する関数 *)
  match lst with
  [] -> []
  | hd::tl -> f hd :: map f tl;;
val map : ('a -> 'b) -> 'a list -> 'b list = 
# map (fun x -> x * x) [1; 2; 3; 4];;
- : int list = [1; 4; 9; 16]
リストは値の集合などを扱うときに使われる。リストに対する操作はListライブラリにいろいろ含まれている。
|
前のページはこちら