GHC.Genericsの提供する型を見る
data V1 p
data U1 p = U1
data (:+:) f g p = L1 (f p) | R1 (g p)
直和
data (:*:) f g p = (f p) :*: (g p)
直積
newtype K1 i c p = K1 { unK1 :: c }
値コンストラクタの引数に当たる型を表す
第1引数はRはRuecursiveを表すと書いてるが、どの辺が再帰なのかわからない #?? e.g. K1 R Int, K1 R Bool
K1 Pというのもあったがdeprecated
newtype M1 i t f p = M1 { unM1 :: f p }
iは、D, C, Sのいずれかを取る
D: Datatype
C: Constructor
tには、メタ情報が含まれる
各iごとに別の値をを取る
Dとのとき
例えば('MetaData "Hoge" "Fuga.Hoge" "main" 'False)は、それぞれ
型名、module名、(mainは知らん)、newtypeかどうかを表す
newtypeならTrue, dataならFalseになる
Cのとき
例えば('MetaCons "H2" 'PrefixI 'False)は、それぞれ
コンストラクタ名、fixity、レコードかどうかを表す
仮にdata I a = I a :&: aみたいな型を定義すれば、InfixIになる
仮にdata R = R { a :: String }みたいな型を定義すれば、最後はTrueになる
Sのとき
Selector名が示される
Record Selectorでない場合も。
data U1 pとか、data V1 pのpの意味
このpがなしで定義するとどうなるか
code:hs
data V1
data U1 = U1
data (f :+: g) = L1 f | R1 g
data (f :*: g) = f :*: g
ここで定義したデータ型をrepresentationとかと呼ぶ
これらは多相ではないので、Rep f :: *と書ける(???????????)
わからんmrsekut.icon
kindが*なのはわかる
fが何なのかわからん
ここで、このようなデータ型を使ってFunctorのinstanceにすることを考える
fmap :: (a -> b) -> Rep f -> Rep f
通常はこんな風にやる
fmap :: (a -> b) -> List a -> List b
つまり、Rep f :: *の場合だと、型引数を取れないので、fmapを実装できない
だからpを追加することで
code:hs
data V1 p
data U1 p = U1
data (f :+: g) p = L1 (f p) | R1 (g p)
data (f :*: g) p = (f p) :*: (g p)
fmap :: (a -> b) -> Rep f a -> Rep f bとできる
But what happens to the type classes that work with * kinds? Our choices are:
の部分、おもろいこと言ってる感じがあるが理解できないので一旦スルー
参考
良い記事
理解しきれてないので、理解が進んでから再読したい