These are exciting times in the OCaml community. Compiler development is proceeding at a brisk pace, with several long-awaited features on the horizon (flambda, multicore, and modular implicits, just to name a few). The tooling has also improved dramatically in the past few years, making the time before OPAM and Merlin seem like a very distant and best forgotten dark age. Moreover, the community has grown to the point where it is very likely that you will find a library that tackles your particular needs, whatever they may be. Some pain points remain, however. In this post I'll address a particularly frustrating one: the issue of library documentation (or lack thereof). Frustrating not only because it is endemic to our community, but also because it can be mitigated with minimal burden to library authors.

Ideally, a library's documentation would consist of an introductory tutorial garnished with multiple examples, plus the API reference. While the latter is indisputably useful, for libraries with a large surface API it is not enough. In such cases, users faced solely with the API reference are likely to scratch their heads wondering where to begin and how the various pieces fit together. The API reference only becomes useful once users have built a proper mental model of the library, which is a lot easier to do after reading through a tutorial.

Unfortunately, if a project includes any documentation at all, it is very likely that consists solely of the API reference rather than a tutorial. The reason is fairly obvious to any developer: the API reference sits right there in the code (in the mli file, usually), and imposes a minimal burden in creation and maintenance. Writing a tutorial, on the other hand, is a whole extra task that robs time away from the actual coding. It's also not as fun.

There is however a middle ground between writing a full-fledged tutorial and not writing one at all. Moreover, it's a middle ground that imposes minimal inconvenience to developers while providing tremendous value to users. I'm talking about simply including some usage examples with your library.

What makes examples so special? Foremost, a good example provides one of the critical advantages of a tutorial: condensing a large API into a concrete starting point. Consider the case of Cohttp, which offers a relatively large API further complicated by the need to support both Lwt and Async backends. Despite this, getting started with Cohttp is actually fairly easy because it includes a couple of trivial examples. Any OCaml developer can look at the half-dozen lines of each example and immediately build a mental model of how the Cohttp library is structured.

Besides the advantages they bring to users, examples are not very burdensome to developers. For one, they can be derived from private examples used in testing. Moreover, it's fairly trivial to keep examples up-to-date with the latest library API, because in most cases you can rely on the compiler doing the heavy lifting of verifying that the example is still valid. All in all, there is an asymmetry at play: a minimal effort on the developer's part will make a tremendous difference to users. Therefore, my plea to OCaml library developers is to please include examples with your libraries!

Now that (hopefully) I've convinced you to exemplify your libraries, you should also consider a few common sense rules for maximising the effectiveness of examples:

  • Place your examples in a directory named examples. This is the de facto standard in the OCaml community.

  • Start simple, even if the example is dummy. Resist the temptation to demonstrate all the awesome features of your library in a single example.

  • Fully qualify identifiers. In other words, avoid global opens and over-using custom operators. Also, note that parenthesised local opens (the Module.(expr) syntax) are preferable to global opens anyway. And if you insist on showing off the powers of conciseness afforded by your library, please consider having two versions of the same example: one using full qualification, and one without.

  • Order your examples. Suppose you have a sundry collection of examples. Simply number them from the simplest to the more complex. Otherwise, users are faced with a directory full of examples, without knowing where to start. (This is the approach I have chosen for the examples for the Lambdoc library.)

  • Include a Makefile or build instructions for the examples, particularly if the building process is not obvious.

  • Keep your examples up-to-date.