我在学习GHC仿制药。在回顾了几个例子之后,我想尝试创建一个通用的Functor
实例(不管GHC能为我自动推导它们)。然而,我意识到我不知道如何使用泛型的参数化数据类型,我见过的所有例子都是*
。这是可能的,如果是的话,如何? (我对SYB等其他类似框架也很感兴趣。)如何使用GHC.Generics(或其他类似的框架)构造泛型函子实例?
9
A
回答
8
使用GHC Generics查找大量示例函数的最佳位置是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
要在数据类型利用这一点,你必须得到Generic1
而非Generic
。 Generic1
表示法的关键区别在于它使用编码参数位置的Par1
数据类型。
3
* -> *
类型的数据类型有Generic1
类。使用它的方式与*
类型的数据类型大致相同,但参数的Par1
也是如此。例如,我用它在我的unfoldable package中。
相关问题
- 1. 如何使用实体框架核心的泛型类型?
- 2. 我如何使用泛型类的构造函数
- 3. 在C#中使用泛型创建类似类型的实例
- 4. 使用泛型类型的参数化构造函数基类
- 5. 我应该在构造函数中实例化其他类吗?
- 6. 实体框架的泛型类型
- 7. Java - 扩展似乎是调用其他类的构造函数
- 8. 构造一个泛型Java类,其中T是foo类或foo的子类
- 9. 如何实例化其构造函数使用yield的对象?
- 10. 如何使用约束构造Applicative实例(类似于使用ContT构造Monad实例)
- 11. 具有非泛型构造函数的泛型F#类型
- 12. 使用泛型类型的Java构造函数
- 13. 从泛型类泛型类中缺少构造函数
- 14. 构造泛型类型
- 15. Java:子类构造函数的super()如何参与实例流?
- 16. 使用实体框架和ADO.NET模型的泛型类型
- 17. 泛型类型的静态构造函数如何工作?
- 18. 如何在其他构造函数中调用构造函数?
- 19. 是否支持非泛型类中的泛型构造函数?
- 20. VB.NET - 如何在泛型类型的实例上调用实例函数委托?
- 21. 泛型和类,在构造函数中决定子类
- 22. 使用构造函数自动装配泛型类型[Spring 4.2.5]
- 23. 使用实体框架4使用ContextBuilder与泛型类创建EDMX/DB架构的例外
- 24. 使用enumset的泛型类的构造函数的问题
- 25. C#泛型 - 类实现其他泛型类
- 26. 使用泛型类型实例化DynamoDBQueryExpression
- 27. 使用实体框架生成实体的构造函数
- 28. 使用Java泛型的接口/抽象类的构造函数
- 29. 如何使用泛型类型数组和泛型类作为构造函数中的参数?
- 30. 的Java:实例化一个泛型类没有默认构造函数
GHC是否会自动导出'Generic1'的实例? –
@PetrPudlák不完全自动。但是通过'DeriveGeneric'语言扩展,你可以使用'派生Generic'以及'派生Generic1'(后者只适用于至少有一个参数的数据类型,最后一个参数类型为'*')。 – kosmikus
@kosmikus谢谢。不幸的是,对于我的目标,我希望能够处理更复杂的类型,所以我可能不得不使用Template Haskell。 –