2013-07-19 7 views
9

私はGHC Genericsを学ぼうとしています。いくつかの例を見直した後、汎用のFunctorインスタンスを作成しようとしました(GHCが自動的にそれらを引き出すことはできません)。しかし、ジェネリックスでパラメータ化されたデータ型をどのように扱うか分かりません。私が見た例はすべて*です。これは可能ですか?はいの場合、どうですか? (私はSYBのような他の同様のフレームワークにも興味があります)GHC.Generics(または他の同様のフレームワーク)を使用して汎用Functorインスタンスを構築する方法は?

答えて

8

GHCジェネリックスを使用してたくさんのサンプル関数を探すには、generic-deriving packageが最適です。そこにはFunctorクラスの一般的な定義があります。 Generics.Deriving.Functorからのコピー(少し簡略化):

class GFunctor' f where 
    gmap' :: (a -> b) -> f a -> f b 

instance GFunctor' U1 where 
    gmap' _ U1 = U1 

instance GFunctor' Par1 where 
    gmap' f (Par1 a) = Par1 (f a) 

instance GFunctor' (K1 i c) where 
    gmap' _ (K1 a) = K1 a 

instance (GFunctor f) => GFunctor' (Rec1 f) where 
    gmap' f (Rec1 a) = Rec1 (gmap f a) 

instance (GFunctor' f) => GFunctor' (M1 i c f) where 
    gmap' f (M1 a) = M1 (gmap' f a) 

instance (GFunctor' f, GFunctor' g) => GFunctor' (f :+: g) where 
    gmap' f (L1 a) = L1 (gmap' f a) 
    gmap' f (R1 a) = R1 (gmap' f a) 

instance (GFunctor' f, GFunctor' g) => GFunctor' (f :*: g) where 
    gmap' f (a :*: b) = gmap' f a :*: gmap' f b 

instance (GFunctor f, GFunctor' g) => GFunctor' (f :.: g) where 
    gmap' f (Comp1 x) = Comp1 (gmap (gmap' f) x) 


class GFunctor f where 
    gmap :: (a -> b) -> f a -> f b 
    default gmap :: (Generic1 f, GFunctor' (Rep1 f)) 
       => (a -> b) -> f a -> f b 
    gmap = gmapdefault 

gmapdefault :: (Generic1 f, GFunctor' (Rep1 f)) 
      => (a -> b) -> f a -> f b 
gmapdefault f = to1 . gmap' f . from1 

データ型でこれを使用するには、むしろGenericよりGeneric1を導出する必要があります。 Generic1表現の主な違いは、パラメータ位置をエンコードするPar1データ型を使用することです。

3

データタイプが* -> *の場合、Generic1クラスがあります。これを使用した作業は、ほとんどの場合、種類が*のデータ型と同じですが、パラメータにはPar1があります。私は例えばunfoldable packageに使っています。

+0

GHCは自動的に 'Generic1'のインスタンスを派生しますか? –

+1

@PetrPudlák完全には自動的にはありません。しかし、 'DeriveGeneric'言語拡張で' Generic1を導出する 'だけでなく、 'Deriving Generic'を使うこともできます(後者は、少なくとも1つのパラメータを持つデータ型に対してのみ機能し、最後のパラメータはkind *である)。 – kosmikus

+0

@kosmikusありがとうございます。残念なことに私の目標ではもっと複雑な種類のものを使いたいので、Template Haskellを使わなければならないでしょう。 –

関連する問題