Haskell 在通用代表上制作包装器

Haskell 在通用代表上制作包装器,haskell,Haskell,对于某些类型,我有一个repa,我使用一些对所有x进行了修改。Rep A x->F(Rep A)x函数,其中F是一个类型族。假设这将所有字段包装在Maybe中。我想做的是将F(repa)序列化为JSONaeson提供序列化泛型类型的函数,但不提供在实际泛型表示上操作的函数 为了解决这个问题,我想我可以写这样的东西 newtype RepWrapper a = RepWrapper (F (Rep a)) 使用泛型实例 instance Generic a => Generic (RepW

对于某些类型,我有一个
repa
,我使用一些
对所有x进行了修改。Rep A x->F(Rep A)x
函数,其中
F
是一个类型族。假设这将所有字段包装在
Maybe
中。我想做的是将
F(repa)
序列化为JSON
aeson
提供序列化泛型类型的函数,但不提供在实际泛型表示上操作的函数

为了解决这个问题,我想我可以写这样的东西

newtype RepWrapper a = RepWrapper (F (Rep a))
使用泛型实例

instance Generic a => Generic (RepWrapper a) where
    type Rep (RepWrapper a) = F (Rep a)
然后我可以在这个包装值上使用
aeson
函数

上面的问题是需要将额外的类型参数指定给
Rep
。据我所知,有三种方法可以做到这一点

newtype RepWrapper a = RepWrapper (forall x. F (Rep a) x)
data RepWrapper a = forall x. RepWrapper (F (Rep a) x)
newtype RepWrapper a x = RepWrapper (F (Rep a) x)
第一种方法让我写
from
函数,第二种方法让我写
to
函数,第三种方法似乎没用


有没有一种方法可以定义包装器,这样我就可以实现整个
Generic
实例?

给定一个数据类型
a
Generic
与泛型表示
repa
同构。在这里,我们想走另一条路。给定一个泛型表示法
r
(这里
r~F(Rep a)
对于某些
a
),我们需要一个数据类型
B
,以便
Rep B~r
。我们将
B
定义为
数据r

data Data r = Data (r ())
r::*->*
的类型参数是phantom(实际上,它是由
Generic1
使用的,没有人使用
Generic1
),因此我们可以用任何东西实例化它,我们选择
()
作为任意默认值

我们将需要将这种幻象性表示为一种约束。一种方法是取
函子
和的连词



另外,我在泛型数据中定义了保留额外参数而不是实例化它,因为这样做实际上很便宜。

只需将额外变量指定为
()
,它无论如何都是幻影(除非使用
Generic1
,但这似乎不太可能)。但是如果
F
是一个类型族,那么对于它映射到的任何类型,您都只需要
ToJSON
实例。@李耀霞如果您只将
指定为
()
,则无法实现
。此外,类型族将表示映射到几乎相同的表示,但字段(在˙K1`constructors中)包装在
中,可能
。通用rep类型没有JSON实例,或者至少它们的实例不是我想要的。好的,谢谢,我更好地了解问题所在。哈哈<代码>幻影
是一个很好的技巧。希望很快在量化的上下文中,我们能够要求直接强制。是的,那会更好!
type Bivariant f = (Functor f, Contravariant f)

phantom :: Bivariant f => f a -> f b  -- Data.Functor.Contravariant

instance Bivariant r => Generic (Data r) where
  type Rep (Data r) = r
  from (Data r) = phantom r
  to = Data . phantom