
I wonder if I am completely off here, but I am surprised that there is no progress on the scoped labels front. The Haskell wiki mentioned that the status quo is due to a missing optimum in the design space, but the same can be said about generic programming in Haskell and yet, GHC ships with Scrap your boilerplate. So we have to resort to type classes hacks instead of a proper solution.
There are various implementations of extensible records available. HList may have the best-supported versions and the most experience, but essentially, they are simple enough to define that some packages ship with their own variants (as long as there is no agreement on the future of the language extensions needed to implement these libraries, there won't be any standard library). See the links on the Haskell wiki [1], though there are also newer entries on the GHC trac wiki [2,3]. The Haskell wiki page also points to my old first class labels proposal, which included a small example implementation based on Daan's scoped labels (there was a more recent implementation of Data.Record which noone seemed interested in, and the fairly new Data.Label suggestion offers a workaround for the lack of first class labels, see [4] for unsupported experimental versions of both). The various accessor packages and generators might be a more lightweight/portable alternative. In particular, they also cover the case of nested accessors. And, going back to your original problem, there is an intermediate stage between data BayeuxMessage = HandshakeRequest { channel :: String , ... } | HandshakeResponse { channel :: String, successful :: Bool, ... } | ... and data HandshakeRequest = HandshakeRequest { channel :: String , ... } data HandshakeResponse = HandshakeResponse { channel :: String, successful :: Bool, ... } ... data BayeuxMessage = HSReq HandshakeRequest | HSRes HandshakeResponse ... namely data HandshakeRequest = HandshakeRequest { ... } data HandshakeResponse = HandshakeResponse { successful :: Bool, ... } ... data BayeuxMessage = HSReq{ channel :: String, request :: HandshakeRequest } | HSRes{ channel :: String, response :: HandshakeResponse } ... Generally, you'll often want to use labelled fields with parameterized types, eg data NamedRecord a = Record { name :: a, ... } type StringNamedRecord = Record String type IntNamedRecord = Record Int and, no, I don't suggest to encoded types in names, this is just an abstract example;-) Mostly, don't feel bound to a single upfront design, refactor your initial code until it better fits your needs, as you discover them. Hth, Claus [1] http://www.haskell.org/haskellwiki/Extensible_record [2] http://hackage.haskell.org/trac/ghc/wiki/ExtensibleRecords [3] http://hackage.haskell.org/trac/ghc/ticket/1872 [4] http://community.haskell.org/~claus/