クラス型
class
キーワードを使用して定義する。Eq
やOrd
はクラス型となり、データ型はクラス型を指定することでクラス型のインスタンスとして振舞うことができる。
クラス型はオブジェクト指向言語でいうところのインターフェースのように、インスタンスが持つ関数の型を定義することができる。
クラス型の定義
クラス型YesNoはa型を引数に取りBool型を返す関数インターフェースを提供する。
class YesNo a where yesno :: a -> Bool
クラス型のインスタンス
Int型とList型をYesNoクラスのインスタンスとして振る舞えるようにする。
instance YesNo Int where yesno 0 = False yesno _ = True instance YesNo [a] where yesno [] = False yesno _ = True
ghci> yesno [] False ghci> yesno (1::Int) True ghci> yesno (0::Int) False
データ型定義時にクラスインスタンスとする場合、derivingでクラス型を与えることで与えられたクラスのインスタンスとして振る舞える。
Functor型クラス
型コンストラクタMaybe
やList
に対する型クラス。中に入った型に作用した後、同じ型コンストラクタに包んで返す関数を定義する。
class Functor f where fmap :: (a -> b) -> f a -> f b
この時、f
は型コンストラクタなので型コンストラクタに包まれたa型をb型に変換して、同じ型コンストラクタに包んだb型を返すという風に読める。
イメージはこんな感じ。
ghci> [ show x | x <- [1,2,3]] ["1","2","3"]
Maybeのfmap
Maybeも型コンストラクタなのでFunctor型のインスタンスとなる。同じものに包まれて、中身の型に関数が作用しているのがわかる。
ghci> fmap (*2) $ Just 1 Just 2 ghci> fmap (*2) $ Nothing Nothing ghci> fmap (show) $ Just 1 Just "1"
リンク
リンク