Years ago when I was in graduate school, there was a period when I became very obsessed with functional programming and the Haskell programming language. (At the dawn of the era of multi-core computation, it was believed that functional programming was one of the most promising technologies that would save the world.) Unlike many other earlier functional languages which allow ad hoc imperative constructions when it comes to IO-related tasks, Haskell is elegant and purely functional. When IO must be done, one programs in Haskell with a mindset that he/she is composing a combination of IO (and other) instructions. The IO instructions, as instructions rather than the realization of them, are purely mathematical and do not interact with the real world. The computation of a Haskell program produces something called an IO monad, and all side effects only take place when the runtime executes the IO monad, which happens outside the functional programming realm. One can argue that this is only a perspective, because a piece of, say, C++ code, as code per se, do not have any side effects either. Side effects only take place when a binary is executed, and the binary is not C++, it’s outside the realm of C++ programming. Well, yes, functional programming IS only a perspective, but imperative programmers just do not think in that way.
Now lets come back to the mysterious monad. It turns out that monads are much, much more powerful than merely an abstraction of IO operations. A whole lot of apparently unrelated programming constructions can be realized with monads, and the resulting code is usually very simple and beautiful. There are monads for old school pessimistic error handling (the Maybe monad), exceptions, lists, state machines, parsers, even software transactional memory (STM) and structured query language (SQL). You name it! I felt my eyesight broaden, and was fascinated by the prospect that I’ll become a very powerful programmer if I master the unqualified, generic MONAD.
So I dug out all articles and tutorials about monads I can find on the Internet (well, except for text books on category theory; I was trying to find a shortcut). And after a long time of struggling, I found myself defeated by the fact that I cannot comprehend this programming construction as simple as three laws, among which at least two if not the third, in my opinion, are trivial! I didn’t have any problem with every one of the specialized monads, and I understood every letter of the monad laws. But the generic monad, I just couldn’t get the hang of it.
Life goes on without one becoming a master monadic programmer. I came back to my bread-earning systems and machine learning programming, and was glad to find that I could still do whatever I needed to do with the good old imperative programming. And with the introduction of lambda (be cautious: the lambda in C++ and other imperative languages are all but functional!) and other nice features to C++11, life after all is becoming better. But deep down inside, this monad thing kept bothering me, and has been, as now I see, fermenting.
Then there came a day, when I was fighting a religious programming language war in a web forum (always a good pass-time), the enlightenment suddenly came to me. And here I’m sharing with you the dark truth behind the power of monads I finally came to understand.
Behind all powers of monads, there is only one true power: the parsing power. Monads can be used in a parser to create internal data structures representing the parsing results of a context-free language (strictly speaking a little more than that, but it doesn’t matter here), to which almost all programming languages belong. The only property that is common to all those specialized monads is that they can all be written in a context free language which can be parsed. The process of monadic programming is nothing more than mentally parsing a piece of imaginary imperative or whatever code and writing down the “internal” representation in monads. It naturally follows that one can mimic with monads any (context-free) programming constructions that can ever be invented. And I’m pretty sure the process can be automated if one doesn’t have to preserve all the syntactic sugar. My hope to become a master programmer by learning to use monads, put in the layman’s terms, is not any more realistic than the hope to become a serial inventor by learning the art of creating text files!
Monad and its equivalents are still nice and powerful as a language for invention. They made it possible to (re-)invent programming constructions without having to create new languages. But very likely they don’t make invention itself any easier. One evidence is that all the monads we so far have seen all have their preexisting counterparts in other languages and libraries. At least now I don’t feel so bad that I cannot become a master monadic programmer.
And speaking of syntactic sugar, people have been feeding on it for a while, and I don’t mind having more of it.