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)
序列化为JSONaeson
提供序列化泛型类型的函数,但不提供在实际泛型表示上操作的函数
为了解决这个问题,我想我可以写这样的东西
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