型クラス

昨日(id:takatoh:20060506:type)の最後にあげた関数の型

Prelude> :type map (\x -> x * 2)
map (\x -> x * 2) :: (Num a) => [a] -> [a]

の中に現れる (Num a) => という部分は,a が Num クラスのインスタンスでなければならないことを表している。つまりこの場合には,引数に 2 を掛けるという関数なのだから,引数は 2 と掛け算ができる型でなければならない。それが Num クラスのインスタンス,というわけだ。
この,型変数 a に対するいわば制約をコンテキスト(context)という。

型クラスというのは,いくつかの型に共通する性質をまとめたもの,というふうに理解したらいいだろうか。
たとえば,「一致するか否かを比較判定できる」という性質は Eq クラスにまとめられているけど,この性質は 文字(Char)や数値(Int,Float)などに共通する。このとき,Char や Int を Eq クラスのインスタンスという。というか,Char や Int は Eq クラスのインスタンスとして定義されている。

クラスに定義されている関数をメソッドといい,Eq クラスには比較のためのメソッド (==) と (/=) が定義されている。

Prelude> :type (==)
(==) :: (Eq a) => a -> a -> Bool
Prelude> :type (/=)
(/=) :: (Eq a) => a -> a -> Bool

Eq クラスのインスタンスである型ならこのメソッドを適用できる。

Prelude> 'a' == 'a'
True
Prelude> 100 == 200
False
Prelude> 1.24 /= 1.25
True

リストでも大丈夫みたいだ。

Prelude> [1,2,3] == [1,2,3]
True

代表的なクラスをいくつか。

Eq Num Show Read Ord

ところで,ふだん Ruby をメインに使っている俺としては,このクラスとインスタンスの関係にはちょっと違和感がある。
Haskell でいう Char とか Int とかの型(type)が Ruby ではクラスであって,その具体的な値(”abc” とか 10 とか)をインスタンスという。Haskell のクラスに当たるものは Ruby には……ないよな。あえて言えばスーパークラスか?……それも違うな。
逆に Ruby のインスタンスに当たるものは Haskell ではなんと言うんだろう。