[Haskell-cafe] blaze-builder and FlexibleInstances in code that aims to become part of the Haskell platform

wren ng thornton wren at freegeek.org
Fri May 20 02:00:00 CEST 2011


On 5/19/11 5:51 PM, Antoine Latter wrote:
> On Thu, May 19, 2011 at 3:06 PM, Simon Meier<iridcode at gmail.com>  wrote:
>
>> The core problem that drove me towards this solution is the abundance
>> of different IntX and WordX types. Each of them requiring a separate
>> Write for big-endian, little-endian, host-endian, lower-case-hex, and
>> uper-case-hex encodings; i.e., currently, there are
>>
>> int8BE   :: Write Int8
>> int16BE :: Write Int16
>> int32BE :: Write Int32
>> ...
>> hexLowerInt8 :: Write Int8
>> ...
>>
>> and so on. As you can see
>> (http://hackage.haskell.org/packages/archive/blaze-builder/0.3.0.1/doc/html/Blaze-ByteString-Builder-Word.html)
>> this approach clutters the public API quite a bit. Hence, I'm thinking
>> of using a separate type-class for each encoding; i.e.,

It seems to me that a better way of handling this would be to explicitly 
define an ADT (or type-level equivalent) for naming the different format 
options. That is, something like this:

     data Endianness = BE | LE | HE
     data Radix      = Binary | Octal | Decimal | Hexadecimal
     ...
     data WIFormat = WIFormat
         { endianness :: {-# UNPACK #-} !Endianness
         , radix      :: {-# UNPACK #-} !Radix
         ...}
     class WriteWI a where
         writeWI :: WIFormat -> Write a

If you're sure that you can get rid of the typeclass overhead, then you 
should be able to get rid of the case analysis on the ADT as well (by 
making sure to always use writeWI fully saturated). But this way, you 
only need to deal with one class and it's obvious how to extend it (as 
opposed to your newtype solution where it's not clear whether the order 
of newtype wrapping matters, etc).

Of course, I'm not advocating that specific ADT for encoding format 
types. For example, it's only in decimal format where there's any 
difference between Word* and Int* types, since the signedness never 
shows up explicitly in binary, oct, or hex representations. There's also 
the issues you've mentioned about whether hex is upper case or lower 
case, whether there's a leading sigil like 0 or 0o for oct, or 0x, \x, 
U+,... for hex. And so on. So you'll need to figure out what all the 
formats are you want to offer, but it should be straightforward to come 
up with an ADT like the one above, and then you can just case match on 
it to choose the specific format.

As for the class, if you run into too much type ambiguity and want to 
avoid the need for type signatures, then you can add an unused argument 
of type @a@ as is common in other core libraries needing to be H98 
compliant.

-- 
Live well,
~wren



More information about the Haskell-Cafe mailing list