10.6 クラスとインスタンスの宣言
前にも書いたけど、Haskellのクラスは型クラスで、型クラスのインスタンスは型。
最初はBool型がEqクラスを実装する例。自分でも手を動かしたかったので、Bool型とEqクラスを自分で定義してみる。演算子はちょっと悩んだけど、%==
と%!=
にしてみた。
data Bool_ = True_ | False_ class Eq_ a where (%==) :: a -> a -> Bool (%!=) :: a -> a -> Bool x %!= y = not (x %== y) instance Eq_ Bool_ where False_ %== False_ = True True_ %== True_ = True _ %== _ = False
Haskellの型クラスはJavaやC#のインターフェースみたいなものだけど、関数のデフォルト実装を書けるところは違うね。
続いてEqクラスを拡張したOrdクラスの例。C#だとIComparable<T>はIEquatable<T>を拡張したインターフェースじゃないけど。
class Eq_ a => Ord_ a where (%<) :: a -> a -> Bool (%<=) :: a -> a -> Bool (%>) :: a -> a -> Bool (%>=) :: a -> a -> Bool min :: a -> a -> a max :: a -> a -> a min x y | x %<= y = x | otherwise = y max x y | x %>= y = x | otherwise = y instance Ord_ Bool_ where False_ %< True_ = True _ %< _ = False b %<= c = (b %< c) || (b %== c) b %> c = c %< b b %>= c = c %<= b
インスタンスの自動導出
おおー、楽だ。Showクラスとか書くの面倒だなと思ってたけど、こんな機能があるならOKだ。
derivingの後ろにクラスを複数書く場合は()
で囲む必要あり。
data Shape = Circle Float | Rect Float Float deriving (Eq, Ord)
モナド型
前に使ったParser型を本当のモナドにした時に、Monadクラスを実装していたこと(と、MonadPlusクラスを実装していたこと)はすでに知ってた。 せっかくなので、Maybe_型を自分で書いてみよう。
data Maybe_ a = Nothing_ | Just_ a deriving Show instance Monad Maybe_ where return x = Just_ x Nothing_ >>= _ = Nothing_ Just_ x >>= f = f x