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