の使い方を勉強しようと思っていますGHC.Generics
。魅力的なトピックですが、難しいです。
ブログ エントリ24 日間の GHC 拡張機能: DeriveGenericを読みながら、値を取得してその をナビゲートする方法を学びましたRep
。わかった。
しかし、ブログエントリBuilding data constructors with GHC Genericsを読んで、構築と値への変換の類似性を説明していRep
て、困惑しました。他の 多く の リソースを読みましたが、大きな助けにはなりませんでした。
ブログエントリには次のコードがあります。まず、以下を構築しRep
ます。
class Functor f => Mk rep f | rep -> f where
mk :: f (rep a)
instance Mk (K1 i c) ((->) c) where
mk = \x -> K1 x
instance (Mk l fl, Mk r fr) => Mk (l :*: r) (Compose fl fr) where
mk = Compose (fmap (\l -> fmap (\r -> l :*: r) mk) mk)
instance (Mk f f') => Mk (M1 i c f) f' where
mk = M1 <$> mk
次に、次の処理を行いCompose
ます。
class Functor f => Apply f a b | f a -> b where
apply :: f a -> b
instance Apply ((->) a) b (a -> b) where
apply = id
instance (Apply g a b, Apply f b c) => Apply (Compose f g) a c where
apply (Compose x) = apply (fmap apply x)
次に、型のあいまいさを処理します。
type family Returns (f :: *) :: * where
Returns (a -> b) = Returns b
Returns r = r
make :: forall b f z. (Generic (Returns b), Apply f (Returns b) b, Mk (Rep (Returns b)) f) => b
make = apply (fmap (to :: Rep (Returns b) z -> (Returns b)) (mk :: f (Rep (Returns b) z)))
わお。
本当に、私はファンクタを返すクラスMk
で、最初に立ち往生しています。mk
私の質問:
mk
戻るとは何ですか?なぜファンクターなのですか?その結果の解釈は何ですか?のK1 i c
インスタンスMk
が、値を受け取って でラップする関数 (これはファンクタであることは理解しています) を返していることがわかりますK1
がmk
、Mk (l :*: r)
とMk (M1 i c f)
は完全に失われています。Compose
から来ていると推測しています。Data.Functor.Compose
つまり、 を実行すると、構成されたファンクターの奥深くで 2 つのレベルが実行されます。しかし、 .内にネストされた s を理解できません。fmap f x
fmap
fmap
Compose
のインスタンスの場合
M1 i c f
、内部の値を でラップするだけだと思っていたので、またはM1
の必要性は私には意味がありません。M1 <$> mk
fmap M1 mk
明らかに、私はこれらのインスタンスの意図や意味、およびこれらのインスタンスがどのように相互作用して final を作成するかを理解しているわけではありませんRep
。誰かが私を啓発しGHC.Generics
、途中で使用する方法の良い説明を提供してくれることを願っています.