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