All Unkept
Posted in: Haskell  —  August 04, 2008 at 08:40 PM

Haskell API docs suck. A lot.

by Luke Plant

Haskell API documentation is very lacking for newbies. For instance, I want to understand how to create and use regexes. If you start at Text.Regex.Posix documentation, it tells you that =~ and =~~ are the high level API, and the hyperlinks for those functions go to Text.Regex.Posix.Wrap, where the main functions are not actually documented at all!

So we look at the type signatures -- here is the first:

(=~) :: (RegexMaker Regex CompOption ExecOption source, RegexContext Regex source1 target) => source1 -> source -> target

So, that leads me to the class declarations for these things. But trying to understand them is rather intimidating:

class RegexOptions regex compOpt execOpt | regex -> compOpt execOpt, compOpt -> regex execOpt, execOpt -> regex compOpt where

Or how about this?

class RegexOptions regex compOpt execOpt => RegexMaker regex compOpt execOpt source | regex -> compOpt execOpt, compOpt -> regex execOpt, execOpt -> regex compOpt where

They are using multi-parameter type classes and functional dependencies. Having read bits of Haskell for a while, I happen to know what they are (vaguely), but I don't really understand them, nor does the above really give me any clue to how to actually use this API.

Google to the rescue. (This is bad: I shouldn't have to google for documentation when I'm already looking at the obvious place for something to be documented). The first result for "haskell regex" is a completely useless and hopeless out of date page, but there is a Haskell regex tutorial on a blog that shows us how to do it, and it is astonishingly simple:

> "bar" =~ "(foo|bar)" :: String

So what is going on? It looks like the library has been designed extremely cleverly so that in the simple case (regex with default options etc), you can use it very easily, but you don't need to use different functions if you want to add regex options. Furthermore, it is polymorphic in its return type, so we can also do this:

> "bar" =~ "(foo|bar)" :: Bool

In fact you can get lists of matches, or lists of match offsets etc -- almost anything you can think, just by specifying (directly or using type inference) the type of the result you want. This is beautifully elegant and clever and I'm sure it gave the designer a warm fuzzy feeling inside (well, it gives me one, and I'm just looking at it). The downside is that if you try to use =~ at a GHCi prompt without a type annotation, you just get a ridiculously unhelpful error.

The problem here is that making the library so clever has also made it utterly impenetrable to the beginner. The main functions are not even documented, and there is no explanation of the crazy type signature. You might say that it is simply a documentation problem, but it is actually a combination of the two -- if the type signature had been something simple, it would have been easy to deduce how to use it. It seems to me that the documentation of a library has got to be proportional to the cleverness of its type signatures, or people are going to be absolutely lost. Since Haskell libraries are almost always implemented by Haskell gurus, and they implement them with themselves in mind (I have no objection to this, they are enthusiasts working for free), they use lots of clever code and advanced Haskell techniques. But this means that if you want people to actually use these libraries (and by consequence Haskell itself), the documentation for Haskell libraries has to be about an order of magnitude better than anything you'd find anywhere else. I suspect it is at least an order of magnitude worse than for something like .NET APIs, which means that relatively speaking the documentation of Haskell is currently in an absolutely dire state.

Sorry, I'm just saying it like it is. These libraries are great when you can get them to work, and I'm really grateful to the authors for their fantastic work, and the effort that has gone into packaging and distributing them (so that installation is literally one short command-line away), but the hurdles are still currently far too great compared to any other language for Haskell to become popular.

Moving forward, I guess one problem is contributing to a library's documentation. There is nothing on the API doc pages that shows you how to do this. I suspect you need to check out the source with darcs (not something I do normally, I just use cabal) and then start email patches or something. Even then, I don't know if I would contribute any documentation -- 'howto' style documentation seems out of place on the API pages, but it is desperately needed.

Comments §

blog comments powered by Disqus