generated at
Generic型クラスの利用
Generic型クラスの利用の仕方について仕組みを度外視して雰囲気だけで流れを見る
既に割と抽象的である「代数データ型」の抽象化の話なので、初見ではややこしいmrsekut

よくある状況として、「データ型は自分で定義」して、「型クラスはLibraryが提供」したものを使う、というのがあるのでそれに沿ってメモっていく
これはわかりやすさのための状況設定でもあるので、実際の利用時はコレに限らない
自分が提供する型クラスの話に置き換えてもいい


登場人物
GHC.Generics - HaskellWikiに概念を合わせておく
目的の型
これは自分で定義したもの
e.g. UserTree
目的の型クラス
これはLibraryによって提供されるもの
上の「目的の型」をこの型クラスのinstanceにしたい状況下を考えている
e.g. Serialize 型クラス


どういう状況か
今自分で定義したようなデータ型 UserTree
hs
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf
を、とあるLibraryが提供している Serialize のinstanceにしたい


Genricを用いない時
自分で Serialize のinstanceを定義する必要がある
hs
instance 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にしたい側はめちゃくちゃ楽になる
DeriveGeneric拡張を有効にする必要があるが、今回のようなケースだけのためにある
deriving Generic と書けるようにするだけ


どうやるか
型クラスの提供者はいくつかの定義をしておく必要がある
GHC.Genericsが提供する V1 (:*:) のようないくつかの型を、 Serialize のinstanceにしておく
hs
instance Serialize V1 where .. instance (Serialize f, Serialize g) => Serialize (f :+: g) where ..
ここでやっていることのイメージとしては
代数データ型を Serialize のinstanceにしている感じ
つまり任意の代数データ型に対して Serialize のinstanceを定義している



まとめると
Generic型クラスを利用することで、
型クラスの利用者はめちゃくちゃ楽になる
型クラスの提供者はちょっと大変になる
通常でも Show Eq derivingできるが、
それと同じようなことを自分の提供する型クラスに対しても行える(Library目線)
ただし、通常は deriving Show と書くのに対し、
deriving Generic と書く
deriving Serialize ではなく
ここの差は重要mrsekut
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になっているよ