1
votes

I'm attempting to serialize data types in Haskell, and would like to know how to serialize a GADT. The method I have attempted looks something like (using 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 ......

However, this does not compile: GHC tells me that Cons1 and Cons2 are not valid constructors. I can serialize standard data types just fine. What is the optimal way to serialize GADTs?

The reason I want to serialize GADTs is since this data type is a key in a Redis Database that I'm using for my project.

1
woops .. I just saw that this will not work at all - the cases you defined yield this functions: Cons1 :: forall a . a -> Gadt Int so I think you are really trying to do something else?Random Dev
You may want to look into instant-generics, which is intended to deal with GADTs generically. I haven't looked very far into it myself yet, but it seems interesting.dfeuer
Yeah, I guess I ddid want Cons1 :: Int -> Gadt Int. Thanks!Timothy Chu

1 Answers

4
votes

disclaimer

this does not answer the question about generics as @luqui pointed out


ok turns out your definition is kindof strange (note that the a in Cons1 :: a -> is a forall a and is not related to the a in Gadt a - I cannot see what you did try to do here - sorry)

Basically you could put any value you want int there like

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

all would give you either a Gadt Int or a Gadt Bool - but when you pattern match on it there is no way to make anything meaningful with the value as it really could be anything (including something which is not an instance of NFData itself)


But in principle you declare instances just like you would with normal ADTs - that is by giving defining rnf in here for the different cases.

So let's say I change your GADT into this:

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

then this instance declaration would be fine:

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