[Haskell-cafe] blaze-builder and FlexibleInstances in code that aims to become part of the Haskell platform
Antoine Latter
aslatter at gmail.com
Wed May 18 20:38:25 CEST 2011
On Wed, May 18, 2011 at 12:32 PM, Simon Meier <iridcode at gmail.com> wrote:
> Hello Haskell-Cafe,
>
>
> There are many providers of Writes. Each bounded-length-encoding of a
> standard Haskell value is likely to have a corresponding Write. For
> example, encoding an Int32 as a big-endian, little-endian, and
> host-endian byte-sequence is currently achieved with the following
> three functions.
>
> writeInt32BE :: Write Int32
> writeInt32LE :: Write Int32
> writeInt32HE :: Write Int32
>
> I would like to avoid naming all these encodings individually.
> Especially, as the situation becomes worse for more elaborate
> encodings like hexadecimal encodings. There, we encounter encodings
> like the utf8-encoding of the hexadecimal-encoding with lower-case
> letters of an Int32.
>
> writeInt32HexLowerUtf8 :: Write Int32
>
> I really don't like that. Therefore, I'm thinking about the following
> solution based on type-classes. We introduce a single typeclass
>
> class Writable a where
> write :: Write a
>
> and use a bunch of newtypes to denote our encodings.
>
> newtype Ascii7 a = Ascii7 { unAscii7 :: a }
> newtype Utf8 a = Utf8 { unUtf8 :: a }
> newtype HexUpper a = HexUpper { unHexUpper :: a }
> newtype HexLower a = HexLower { unHexLower :: a }
> ...
>
> Assuming FlexibleInstnaces, we can write encodings like the above
> hex-encoding as instances
>
> instance Write (Utf8 (HexLower Int32)) where
> write = ...
>
> This composes rather nicely and allows the implementations to exploit
> special properties of the involved data. For example, if we also had a
> HTML escaping marker
>
> newtype Html a = Html { unHtml :: a }
>
> Then, the instance
>
> instance Write (Utf8 (HTML (HexLower Int32))) where
> write (Utf8 (HTML (HexLower i))) = write (Utf8 (HexLower i))
If I were authoring the above code, I don't see why that code is any
easier to write or easier to read than:
> urf8HtmlHexLower i = utf8HexLower i
And if I were using the encoding functions, I would much prefer to see:
> urf8HtmlHexLower magicNumber
In my code, instead of:
> write $ Utf8 $ HTML $ HexLower magicNumber
In addition, this would be difficult for me as a developer using the
proposed library, because I would have no way to know which
combinations of newtypes are valid from reading the haddocks.
Maybe I'm missing something fundamental, but this approach seems more
cumbersome to me as a library author (more boilerplate) and as the
user of the library (less clarity in the docs and in the resultant
code).
Antoine
More information about the Haskell-Cafe
mailing list