[Haskell-cafe] Can we do better than duplicate APIs? [was:
robdockins at fastmail.fm
Sat Mar 24 11:29:48 EDT 2007
On Friday 23 March 2007 18:55, Benjamin Franksen wrote:
> [sorry for the somewhat longer rant, you may want to skip to the more
> technical questions at the end of the post]
> Twan van Laarhoven wrote:
> > I would like to announce version 0.3 of my Data.CompactString library.
> > Data.CompactString is a wrapper around Data.ByteString that represents a
> > Unicode string. This new version supports different encodings, as can be
> > seen from the data type:
> > [...]
> > Homepage: http://twan.home.fmf.nl/compact-string/
> > Haddock: http://twan.home.fmf.nl/compact-string/doc/html/
> > Source: darcs get http://twan.home.fmf.nl/repos/compact-string
> After taking a look at the Haddock docs, I was impressed by the amount of
> repetition in the APIs. Not ony does Data.CompactString duplicate the whole
> Data.ByteString interface (~100 functions, adding some more for encoding
> and decoding), the whole interface is again repeated another four times,
> once for each supported encoding.
I'd like to mention that as maintainer of Edison, I face similar difficulties.
The data structure interfaces have scores of functions and there are about 20
different concrete implementations of various sorts. Even minor interface
changes require a lot of tedious editing to make sure that everything stays
> The problems I (for-)see are for maintenance and usability, both of which
> are of course two sides of the same coin. For the library implementer,
> maintenance will become more difficult, as ever more of such 'almost equal'
> interfaces must be maintained and kept in sync.
This is true. For the specific case of Edison, this is not too bad because all
the implementations are currently in one package and under the control of one
person (namely, me). That might, however, change in the future. Obviously,
it is a problem _now_ for the ByteString and friends.
> One could use code
> generation or macro expansion to alleviate this, but IMO the necessity to
> use extra-language pre-processors points to a weakness in the language; it
> be much less complicated and more satisfying to use a language feature that
> avoids the repetition instead of generating code to facilitate it.
I've considered something like this for Edison. Actually, I've considered
going even further and building the Edison concrete implementations in a
theorem prover to prove correctness and then extracting the Haskell source.
Some sort of in-langauge or extra-language support for mechanicly producing
the source files for the full API from the optimized "core" API would be
quite welcome. Handling export lists, haddock comments, typeclass instances,
etc, are quite tedious.
I have to admit, I'm not sure what an in-language mechanism for doing
something like this would look like. Template Haskell is an option, I
suppose, but its pretty hard to work with and highly non-portable. It also
wouldn't produce Haddock-consumable source files. ML-style first class
modules might fit the bill, but I'm not sure anyone is seriously interested
in bolting that onto Haskell.
> Here are some raw ideas:
> One reason why I think type classes have not (yet) been used to reduce the
> amount of API repetition is that Haskell doesn't (directly) support
> abstraction over type constraints nor over the number of type parameters
> (polykinded types?). Often such 'almost equal' module APIs differ in
> exactly these aspects, i.e. one has an additional type parameter, while yet
> another one needs slightly different or additional constraints on certain
> types. Oleg K. has shown that some if these limitations can be overcome w/o
> changing or adding features to the language, however these tricks are not
> easy to learn and apply.
I mostly put these kinds of type system tricks in the same category as TH:
hard to use and non-portable.
> Or maybe we have come to the point where Haskell's lack of a 'real' module
> system, like e.g. in SML, actually starts to hurt? Can associated types
> come to the rescue?
I'm not familiar enough with associated types to know if they would help with
these sorts of problems. Can someone more knowledgable comment?
More information about the Haskell-Cafe