Haskell中GADT的通用实例

时间:2016-02-15 20:15:47

标签: haskell serialization

我正在尝试在Haskell中序列化数据类型,并想知道如何序列化GADT。我试过的方法看起来像(使用Control.DeepSeq):

data Gadt a where 
  Cons1 :: Int -> Gadt Int
  Cons2 :: Bool -> Gadt Bool

instance NFData Cons1 where rnf = genericRnf
instance NFData Cons2 where rnf = genericRnf

deriveSafeCopy ......

但是,这不会编译:GHC告诉我Cons1和Cons2不是有效的构造函数。我可以很好地序列化标准数据类型。序列化GADT的最佳方法是什么?

我想序列化GADT的原因是因为这个数据类型是我用于项目的Redis数据库中的一个键。

1 个答案:

答案 0 :(得分:4)

声明

这不能回答有关generics的问题,因为@luqui指出

确定您的定义有点奇怪(请注意a中的Cons1 :: a ->forall a且与a中的Gadt a无关 - 我看不到你在这里做了什么 - 对不起)

基本上你可以把你想要的任何值放在那里

- Cons1 "Hello" -- :: Gadt Int
- Cons2 'c'     -- :: Gadt Bool
- Cons2 [1,2,3] -- :: Gadt Bool

所有人都会给你一个Gadt IntGadt Bool - 但是当你对它进行模式匹配时,没有办法对这个值有任何意义,因为它实际上可能是任何东西(包括不是NFData本身的实例

但原则上你就像使用普通ADT一样声明实例 - 就是在这里为不同的情况提供定义rnf

所以我想说我将你的GADT变成了这个:

data Gadt a where 
  Cons1 :: Int  -> Gadt Int
  Cons2 :: Bool -> Gadt Bool

然后这个实例声明就可以了:

instance NFData (Gadt a) where
    rnf (Cons1 a) = rnf a
    rnf (Cons2 a) = rnf a