Generic型クラスの利用
既に割と抽象的である「代数データ型」の抽象化の話なので、初見ではややこしい

よくある状況として、「データ型は自分で定義」して、「型クラスはLibraryが提供」したものを使う、というのがあるのでそれに沿ってメモっていく
これはわかりやすさのための状況設定でもあるので、実際の利用時はコレに限らない
自分が提供する型クラスの話に置き換えてもいい
登場人物
目的の型
これは自分で定義したもの
e.g. UserTree
型
目的の型クラス
これはLibraryによって提供されるもの
上の「目的の型」をこの型クラスのinstanceにしたい状況下を考えている
e.g. Serialize
型クラス
どういう状況か
今自分で定義したようなデータ型 UserTree
hsdata UserTree a = Node a (UserTree a) (UserTree a) | Leaf
を、とあるLibraryが提供している Serialize
のinstanceにしたい
Genricを用いない時
自分で Serialize
のinstanceを定義する必要がある
hsinstance Serialize UserTree where
...
...
今は UserTree
だけを考えているが、 UserTree2
、 UserTree3
のような型も出てきて、それらも全て Serialize
のinstanceにしたい場合に、めんどい
逆に、今は Serialize
だけを考えているが、 Serialize2
、 Serialize3
のような型クラスも出てきたときも同様にめんどい
Genricを用いている時
これは型クラスの提供者がGenricを用いている時という意味
これで目的が達成される
hs{-# LANGUAGE DeriveGeneric #-}
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf deriving (Generic)
利用者がやることはこれだけ。
Serialize
のinstanceにしたい側はめちゃくちゃ楽になる
deriving Generic
と書けるようにするだけ
どうやるか
型クラスの提供者はいくつかの定義をしておく必要がある
GHC.Genericsが提供する
V1
や
(:*:)
のようないくつかの型を、
Serialize
のinstanceにしておく
hsinstance Serialize V1 where
..
instance (Serialize f, Serialize g) => Serialize (f :+: g) where
..
ここでやっていることのイメージとしては
代数データ型を Serialize
のinstanceにしている感じ
つまり任意の代数データ型に対して Serialize
のinstanceを定義している
まとめると
Generic型クラスを利用することで、
型クラスの利用者はめちゃくちゃ楽になる
型クラスの提供者はちょっと大変になる
それと同じようなことを自分の提供する型クラスに対しても行える(Library目線)
ただし、通常は deriving Show
と書くのに対し、
deriving Generic
と書く
deriving Serialize
ではなく
ここの差は重要

deriving Generic
とすることで、 deriving Serialize
と同様の効果が得られる
ということは、 deriving Generic
とすれば、
Serialize
に限らず、Genericに対応した他の型クラスのinstanceにも自動でなっていることも意味する
つまり、あるdata型に対して deriving Generic
すれば、「任意の「任意の代数データ型のinstanceにできる型クラス」」のinstanceにできる
Generic型クラスの嬉しさをそれぞれの立場で雑にまとめると
利用者→instanceの実装を省略できて嬉しい
提供者→自分の提供する型クラスをdervingできるようになって嬉しい
deribing Generic
という記述を見たときに連想できること
例えば、LibraryのUsageに「 deriving Generic
と書いてね」とあった場合に何を意味するか
あるいは、コードリーディングしてたら、 deriving Generic
を見かけた場合に何を意味するか
これは以下のようなことを表す
そのLibraryが提供する(Genericに対応した)型クラスのinstanceにしようね
そのコードが利用しているLibraryの中の(Genericに対応した)何らかの型クラスのinstanceになっているよ