如何使用GHC.Generics(或其他类似的框架)构造泛型Functor实例? [英] How to construct generic Functor instances using GHC.Generics (or other similar frameworks)?
问题描述
Functor
实例(不管GHC能为我自动派生它们)。但是,我意识到我不知道如何使用泛型的参数化数据类型,我见过的所有示例都是 *
。这是可能的,如果是的话,如何? (我也对其他类似的框架感兴趣,例如SYB)。寻找大量示例的最佳位置使用GHC Generics的函数是 通用派生
包。那里有一个 Functor
类的通用定义。从 Generics.Deriving.Functor
:
class复制(稍微简化) GFunctor'f其中
gmap'::(a - > b) - > f a - > fb
实例GFunctor'U1其中
gmap'_ U1 = U1
实例GFunctor'Par1其中
gmap'f(Par1 a)= Par1 (fa)
实例GFunctor'(K1 ic)其中
gmap'_(K1 a)= K1 a
实例(GFunctor f)=> GFunctor'(Rec1 f)其中
gmap'f(Rec1 a)= Rec1(gmap f a)
实例(GFunctor'f)=> GFunctor'(M1 i c f)其中
gmap'f(M1 a)= M1(gmap'f a)
实例(GFunctor'f,GFunctor'g)=> GFunctor'(f:+:g)其中
gmap'f(L1 a)= L1(gmap'fa)
gmap'f(R1 a)= R1(gmap'fa)
实例(GFunctor'f,GFunctor'g)=> GFunctor'(f:*:g)其中
gmap'f(a:*:b)= gmap'fa:*:gmap'fb
实例(GFunctor f,GFunctor'g )=> GFunctor'(f:.g)其中
gmap'f(Comp1 x)= Comp1(gmap(gmap'f)x)
class GFunctor f其中
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
要在一个数据类型上使用它,你必须派生 Generic1
而不是
Generic
。 Generic1
表示的关键区别在于它使用编码参数位置的 Par1
数据类型。
I'm trying to learn GHC Generics. After reviewing several examples, I wanted to try to create a generic Functor
instances (disregarding that GHC can derive them automatically for me). However, I realized I have no idea how to work with a parametrized data types with Generics, all the examples I've seen were of kind *
. Is this possible, and if yes, how? (I'm also interested in other similar frameworks, such as SYB.)
The best place to look for lots of example functions using GHC Generics is the generic-deriving
package. There's a generic definition of the Functor
class in there. Copying (slightly simplified) from 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
To use this on a datatype, you have to derive Generic1
rather than Generic
. The key difference of the Generic1
representation is that it makes use of the Par1
datatype that encodes parameter positions.
这篇关于如何使用GHC.Generics(或其他类似的框架)构造泛型Functor实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!