Features Download
From: S. Alexander Jacobson <alex <at> alexjacobson.com>
Subject: SYB and/or HList for XML, deserialization and collections
Newsgroups: gmane.comp.lang.haskell.cafe
Date: Tuesday 26th December 2006 23:24:00 UTC (over 11 years ago)
Having just done a major refactor of the HAppS HTTP API to make it 
much much easier to use, I am now thinking about simplifying the 
current boilerplate associated with XML serialization and state 

In the case of XML, Currently the developer must manually write 
ToElement for every type he/she wants to output.  HAppS provides 
functions that makes doing this a lot easier if the types are Haskell 
records with field labels of the form:

    data Animal = Animal {key::Int, name:: String, breed::Breed,

Looking at the XML example from the SYB site, a shift to SYB means 
shifting from Record types with field labels to identifying fields by 
their types so e.g.

    data Animal = Animal Key Name Breed Price
    type Key = Int
    type Name = String
    type Species = Cow | Sheep
    type Price = Float

This model seems ok, but adds some verbosity.  It also entails a 
learning curve because either you also have field labels or you end up 
with non-standard extra code to access fields.  In this context, HList 
provides good record functionality and a little template haskell makes 
it easy to code so we end up with e.g.

   $(hList_labels "Animal" "key name breed price")
   type Breed = Cow | Sheep

This seems superior from a programming perspective because we have 
good record functionality (and implicitly support for XML 
namespaces!), but we lose something on the XML side.  In particular, 
we end up with two new problems:

1. We no longer have type names, so we can't automatically generate an 
XML element name from an default HList record.  The solution may be to 
define something like this:

   typeName name item = typeLabel .=. name .*. item
   animal = typeName "animal"
   myAnimal = animal .*. breed .=. Cow

And since update and extension are different functions, if we hide 
"typeLabel" from the apps then this gets very safe (or we expose it 
and get a form of typesafe coerce).

2. We don't know how to deal with non-atomic field values e.g.
Cow> makes sense, but we probably 
don't want read/show for product types.  Perhaps it is possible to use 
overlapping instances to do something like:

   instance ToElement HCons a b where ...
   instance ToElement a where toElement = show

But perhaps we can use SYB to allow us to distinguish between atomic 
and non-atomic types and handle appropriately.  I have to say I don't 
think I undersand the SYB papers well enough to give an example.

Note: I can't find an actual example of generating XML from HLists in 
any of the HList docs so it may be that it is not actually as easy as 
it looks.  All of this may be an open issue in theory as well as 

== Deserialization ==

HAppS periodically checkpoints application state to disk.  Developers 
may want to add or remove fields from their state types for from data 
types used by their state types.  The current solution is to have the 
developer assign a version number to state.  If state changes then the 
developer provides dispatch to a deserialization function based on 
that version number.

It is not at all clear from either the SYB or the HList papers how to 
deserialize generally.  That being said, the HList library provides a 
way to call functions with optional keyword arguments that looks like 
it would also generalize to schema transitions.

Anyone who has some experience with this issue in the context of 
HList or SYB?

== Haskell Collections ==

Currently HAppS developers use e.g. Data.Set or Data.Map as collection 
types for their application.  If we push devlopers to use HList for 
eveything then they are going to need a way of handling collections of 
Hlist items.  My sense is that HList style data structures can't be 
stored by Data.Map or Data.Set because they are not heterogenous 
collection types (and will break simply from varying the order of 
field names).  If we use HList as the assumed record type, then I 
think we need to recode Data.Map and Data.Set for them.  Has anyone 
implemented more interesting collection types for HList objects?


PS Obviously people can continue to use regular haskell types and 
implement stuff manually.  My goal here is to support people who want 
more automation and are willing to learn HList or SYB in order to get 
CD: 2ms