Deriving (de)serialization for GADT and Advanced Data Types

Hi all,

I’m working on a project where I’d like to automatically derive (de)serialization instances for datatypes. Right now I’m experimenting with libraries like aeson and cborg as a proof of concept, since they integrate nicely with GHC.Generics for standard ADTs.

However, some of my datatypes are GADTs, and GHC.Generic doesn’t support them. Example context:
:backhand_index_pointing_right: myproject/src/Main.hs

From what I can tell, there are alternative generic programming libraries that do handle GADTs, such as kind-generics. So my questions are:

  • Are there (de)serialization frameworks that can derive instances from these alternative generic representations (like kind-generics), instead of relying only on GHC.Generic?

  • Or is Template Haskell or some other custom approach ( like writing my own cborg or aeson derivation functionality for kind-generics ) the only practical path for automatic deserialization right now ? If so, i would manually write the (de)serialization for GADTs

My current use of aeson and cborg is just exploratory — if there’s another framework that supports GADTs directly, that would be perfectly fine too.

NOTE: The datatypes I’m dealing with are GADTs. But if that assumption is incorrect, please let me know. In any case, here’s the documentation for the GHC.Cmm module, which is a submodule of GHC in the ghc package on Hackage.

Thanks in advance.

Apologies in advance that I can not provide anything like a solution to the problem, but how do you expect something like

data ExistentialNumber where
  Number :: Integral a => a -> ExistentialNumber

would be deserialized? Isn’t deserialization of non-monomorphic types (that hide inside GADTs) an ill-posed problem? Perhaps this thread contains useful methods to bring a GADT into a better serializable form.

I’m not aware of any serialization framework that deals with GADTs.

For metaprogramming, Template Haskell is going to be more straightforward and with more predictable performance than generics-based alternatives. But if you really want to, it should be possible with generics as well.

Isn’t deserialization of non-monomorphic types (that hide inside GADTs) an ill-posed problem?

Yes in full generality it’s an ill-posed problem, particularly when dealing with class constraints. But the GADTs in GHC.Cmm don’t involve classes, only equality constraints as far as I can tell, so this is a more restricted use case that seems reasonable.

1 Like

Indeed, most (if not all) GADTs there appear to have phantom type parameters of kinds other than Type. That is already something that plain Generics has to be able deal with. So if a constructor has type

forall p. TypeNotInvolving_p -> T p

then its parser should have type forall p. Parser (T p) since by parametricity the actual data can not hold any information concerning p, right?

But if the p :: 'P is not universally quantified and furthermore is of a kind that was promoted from a data type P (like Extensibility), then we’d want to somehow serialize the phantom type p, as it is essentially a tag with an element of P. Internally, we’d want a translation

monomorphize :: T (p :: 'P) -> (P,whatever)
polymorphize :: (P,whatever) -> Maybe (T p)

where the latter can only succeed if the P element matches the promoted type p. At least the former can be aided by the reflection package.