fugafuga.write

日々のログ



すごいH本 part49

Eq 型クラスの内部

Eq は等値性判定ができる値の型クラス。==/= という関数を定義している。

標準ライブラリにおける Eq 型クラスの定義

class Eq a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool
    x == y = not (x /= y)
    x /= y = not (x == y)

class Eq a where でEqという名前の型クラスの定義となる。 a は型変数。 関数定義されているが、型宣言だけでもよい。 この場合は関数の実態が実装されている(デフォルト実装)。 型クラス定義に含まれる関数には、最終的にちょっと特別な型が付くとのこと。

交通信号データ型

data TrafficLight = Red | Yellow | Green

Eq インスタンスを自分で作る

instance Eq TrafficLight where
    Red == Red = True
    Green == Green = True
    Yellow == Yellow = True
    _ == _ = False

instance キーワードを使用してインスタンスを作成している。 新しい型クラスを定義するのが class で、型を型クラスのインスタンスにするのが instance

型クラス宣言の中で==/=を使って二つ関数を実装したが、 ==を定義するために/=を使い、/=を定義するために==を使っていた。

インスタンス宣言ではそのどちらか一方だけを上書きすればよい。 これを型クラスの最小完全定義(minimal complete definition)という。

インスタンスになろうとする型をクラスの宣伝文句のとおりに振る舞わせるために、 最低限定義する必要のある関数たちがあるということ。Eq の最小完全定義を満たすには、 ==/=のいずれかを上書きする必要がある。

もし Eq の定義が以下のみだった場合

class Eq a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool

Eq のインスタンスを作るために、両方の関数を定義する必要がある。

信号機型のインスタンス宣言の場合、 パターンマッチを使って==の定義をしている。 まず等しい場合を全て指定し、最後に必ず合致するパターンを置いて、 その他のパターンを定義している。

Show のインスタンスにもする

instance Show TrafficLight where
    show Red = "Red light"
    show Yello = "Yellow light"
    show Green = "Green light"

実行

*Main> Red == Red
True
*Main> Red == Yellow
False
*Main> Red `elem` [Red, Yellow, Green]
True
*Main> [Red, Yellow, Green]
[Red light,Yellow light,Green light]

所感

型クラスは振る舞いが抽象化されていて、その型クラスのインスタンス宣言で具体的な振る舞いを宣言するという感じか。

最小完全定義はインスタンス宣言時に最低限定義しないといけない関数で、型クラス宣言にデフォルト実装が書かれていると全パターン定義しなくても済む。

むっず。