ヴァリアントの応用:多相的ヴァリアント

多相的関数が型情報をパラメータ化できるのと同じように,ヴァリアントの定義の一部をパラメータ化することができる。

# type 'a mylist = Nil | Cons of 'a * 'a mylist;;
type 'a mylist = Nil | Cons of 'a * 'a mylist

‘a がパラメータ化された部分。このヴァリアントは Cons の引数にどんな型でも取ることができる。たとえば整数:

# let n1 = Cons (1, Nil);;
val n1 : int mylist = Cons (1, Nil)
# let n2 = Cons (2, n1);;
val n2 : int mylist = Cons (2, Cons (1, Nil))

文字列でも:

# let s1 = Cons ("a", Nil);;
val s1 : string mylist = Cons ("a", Nil)
# let s2 = Cons ("b", s1);;
val s2 : string mylist = Cons ("b", Cons ("a", Nil))

多相的レコード

多相的な定義はレコードでもできる。次の定義は,既存のデータに「位置情報」を付け加える,というもの。

# type 'a with_location = {loc_x : float; loc_y : float; body : 'a};;
type 'a with_location = { loc_x : float; loc_y : float; body : 'a; }

文字に「位置情報」をつけてみると:

# let c = {loc_x = 50.0; loc_y = 100.0; body = 'X'};;
val c : char with_location = {loc_x = 50.; loc_y = 100.; body = 'X'}

同様に整数に:

# let n = {loc_x = 100.0; loc_y = 100.0; body = 100};;
val n : int with_location = {loc_x = 100.; loc_y = 100.; body = 100}

同じ型で文字も整数も扱える。

ただし,具体的な値は別の型(char with_location と int with_location)になるので,一つのリストに入れるようなことはできない。

# let l = [c; n];;
Characters 12-13:
let l = [c; n];;
^
This expression has type int with_location but is here used with type
char with_location