
I'm trying to write an AMQP framing layer. AMQP has two very similar union types: there is a "variant" that contains a single item, and an "array" which consists of a list of elements of the same type. So I thought I could define a "Unit" type container thus:
newtype Unit a = Unit {unUnit :: a}
So now I can say:
type AmqpVariant = AmqpVariantBase Unit type AmqpArray = AmqpVariantBase []
Then the AmqpVariantBase type looks something like this (except that it doesn't work, see below):
data forall a . (AmqpWire a, AmqpWire (c a)) => AmqpVariantBase c = AmqpVarBin8 (c Bin8) | AmqpVarInt8 (c Int8) | AmqpVarUint8 (c Word8) | AmqpVarChar (c Word8) | AmqpVarBoolean (c Bool) | AmqpVarBin16 (c Bin16) | AmqpVarInt16 (c Int16) | AmqpVarUint16 (c Word16) | AmqpVarBin32 (c Bin32) | AmqpVarInt32 (c Int32) -- And on for about 20 more types, including compound types.
All AMQP types have to be seralised, so I've defined a class "AmqpWire" for serialisation in AMQP format. All the individual types (Bin8, Int8 etc) are instances of this class. I've also defined instances for Unit and [] such as:
instance (AmqpWire a) => AmqpWire (Unit a) where amqpPut = amqpPut . unUnit amqpGet = map Unit amqpGet
The problem is with the type constraint for AmqpVariantBase. I need to say "AmqpWire (c a)" without explicitly listing all the values of "a" (i.e. Bin8, Int8, etc) because any time I use AmqpVariantBase I have to repeat the same constraint. How do I do this? Paul.