型クラス

昨日(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 ではなんと言うんだろう。