在通用Rep上创建一个包装器

时间:2018-04-11 11:25:45

标签: haskell

我使用Rep A函数修改某种类型forall x. Rep A x -> F (Rep A) x,其中F是一个类型系列。让我们说这包裹了Maybe中的所有字段。我想要做的是将F (Rep A)序列化为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实例?

1 个答案:

答案 0 :(得分:1)

给定数据类型> humcon seqnames start end TAS Proxy.start Proxy.end Assembly_NCBI 1 6 28179560 28294888 rs1635 rs78270345 rs4711167 GRCh38.p7 2 3 52833805 52847601 rs3617 rs3617 rs2071044 GRCh38.p7 3 15 91426560 91426560 rs4702 rs4702 rs4702 GRCh38.p7 4 19 45382034 45382034 rs6859 rs6859 rs6859 GRCh38.p7A给出通用表示Generic的同构。在这里,我们想要反过来。给定通用表示Rep A(此处为r r ~ F (Rep A)),我们希望数据类型AB。我们将Rep B ~ r定义为B

Data r

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

我们需要将幻象表达为约束。一种方法是采用Generic1Contravariant的结合。

()

我还在 generic-data 中定义了Data,其中我保留了额外的参数而不是实例化它,因为它实际上很便宜。