データ型に依存しないプログラミング方式をジェネリックプログラミングといいます。データ型を抽象化することで、データ型の違いによるコードの重複を避けることができます。
実際にどのようなものか見ていきましょう。ふたつの値を入れ替えるswap関数を定義します。
> swap (x,y) = (y,x) val swap : 'a * 'b -> 'b * 'a
・int型でのswap関数使用例
> swap (1,2);; val it : int * int = (2, 1)
・string型でのswap関数使用例
> swap ("yamada", "nakamura");; val it : string * string = ("nakamura", "yamada")
このように、swap関数はデータ型に依存せず、ふたつの値を入れ替えるという機能を提供しています。
もしジェネリックプログラミングを導入しなければ、int型用のswap関数、string型用のswap関数など、型ごとにswap関数を用意する必要がでてきます。
ジェネリックプログラミングは型をパラメタ化する必要があります
もう一度swap関数を示します
> swap (x,y) = (y,x) val swap : 'a * 'b -> 'b * 'a
注目していただきたいのが、swap関数の評価で'a 'bという型が登場していることです。
これらは型変数と呼ばれ、'a 'b ともにswap関数を実行するときに与えられた引数の型に置き換えられます。
型変数を使った型定義には行前置と後置の2種類の定義方法があります。
> type 'a one = { one : 'a };; type 'a one = {one: 'a;}
> type one<'a> = { one : 'a };; type one<'a> = {one: 'a;}