« Puffball Fungus | Main | Another Phantom Crane Fly »
Thursday
Mar112010

Monads as Overloadable Semicolons

A comment by Heinrich Apfelmus on a post by Eric Raymond:

"A simpler way to think about monads is as a hack to turn function composition into a way of forcing the sequencing of function calls, or the functional-programming equivalent of a shell pipeline."

This is probably a good first mental approximation of the IO monad, but it’s not a good way to think about monads in general. They are best understood as imperative mini-languages where you can program your own semicolon “;“. The selection of possible side-effects is huge: state, logging, exceptions, non-determinism, coroutines, … . In particular, non-determinism does not fit the “ensure evaluation order” picture.

The equivalent of a shell pipeline is plain function composition (.) coupled with lazy evaluation, at least if the shell commands are essentially side-effect free.

And a comment by Paul Johnson on the same post:

Its important to distinguish between the definition of a monad (roughly, its a type with a couple of operators defined) and the several ways that monads are used in Haskell.

*One* of those ways is to sequence several operations in some context, and one of those contexts is “IO”. This is indeed a neat hack, but the big news is that monads are not just a way to force IO semantics into a pure language, they are a way to introduce any kind of sequencing semantics you might want. Its a bit like having an overloadable semicolon; what do you want “{x;y;z}” to mean?

For instance, for one application I wrote a threaded discrete event simulation framework in Haskell using a combination of continuation and state monads with IO (because a suspended thread is actually just a continuation). This let me write application-level code with multiple threads where “delay (hour 1)” only delayed the thread long enough for the next hours-worth of simulated events to happen in other threads, rather than 1 hour of wall-clock time.

This is important because requirements are often expressed in terms of the form “do this, then do that”, where “then” has a domain-specific meaning. If you can capture that meaning in a monad then suddenly you have code that can be read and understood by a domain expert, which greatly reduces the opportunities for error.

Reader Comments

There are no comments for this journal entry. To create a new comment, use the form below.

PostPost a New Comment

Enter your information below to add a new comment.
Author Email (optional):
Author URL (optional):
Post:
 
All HTML will be escaped. Hyperlinks will be created for URLs automatically.