プログラミング言語SML#解説 4.0.0版
7 MLプログラミング入門

7.20 多相型を持つ関数

「式は型が正しい限り自由に組み合わせることができる」 という原則を最大限に活かすためには,組み合わせを実現する関数は,種々の型 に対応している必要があります. 前節のリストを構成する関数(演算子)::の型は以下の通りです.

# op ::;
val it = fn : [’a. ’a * ’a list -> ’a list]

opは,中置演算子を関数適用の構文で使うための接頭語です. この式は,::が,任意の型’aと それと同じ型’aの要素とするリスト’a listを受け取って, ’aの要素とするリスト’a listを返す関数を表しています. ここで使われる’aは任意の型を表す型変数です. また[’a.]は「すべての型 ’aについて,」である,との表明を表します. このように型変数を含み,種々の型のデータに利用できる関数を 多相関数と呼びます. さらに,これら多相関数を組み合わせて定義された関数も以下のように 多相型を持ちます.

# fun cons e L = e :: L;
val cons = fn : [’a. ’a -> ’a list -> ’a list]

MLは,式の組み合わせによるプログラミングを最大限にサポー トするために,関数定義に対して,その関数のもっとも一般的な使い方 を許すような,最も一般的な多相型を推論します. 以下の関数定義を考えてみましょう.

fun twice f x = f (f x);

この関数は,関数と引数を受け取り,関数を引数に2回適用します. このふるまいを考えると,以下の型が最も一般的な利用を許す型である とが理解できるでしょう.

[’a. (’a -> ’a) -> ’a -> ’a]

実際MLでは以下のように推論されます.

# fun twice f x = f (f x);
val twice = fn : [’a. (’a -> ’a) -> ’a -> ’a]