As I said when talking about Learning Phases, one of the things that happens when I’m trying to learn a new thing is that I build an analogy in terms of something I do understand. This can be dangerous when the analogy is wrong. I’m currently hanging on to the analogy that follows, so I’m publishing it as a straw man argument in the hope that those with more experience than me can critique it and help improve my understanding.
Proposition: Monads are what objects are supposed to look like
Throw away everything you know about Object-Oriented programming, particularly if you know Objective-C, Java, C++ or C#. Now go and read the first edition (the straightforward one, not the detective-novel second edition) of Object-Oriented Software Construction by Bertrand Meyer. You’ll find the principle of Command-Query Separation, that an object’s interface should provide distinct facilities for manipulating and investigating that object. Consider an object as an enclosed module analogous to an electronic circuit[*], with switches you can flip and lights you can observe. Watching a light shouldn’t also have the effect of flipping a switch, and you shouldn’t have to flip a switch in order to watch a light.
How could a language support that principle? Clearly imperative programming is too general, as it lets me mix commands and queries in the same place. What I need is an operation that lets me bind sequential commands together, taking
an object in state a and
a function that turns state a into state b and creating
an object in state b. I also need an operation that lets me run a query, taking
an object in state a and returning
a value corresponding to a. Given those, and assuming the single responsibility principle has driven me to the point where my object does one thing and can be represented by a single command and query, then the interface on my object is complete.
Interestingly and usefully, except in the (common-ish) special case where my object needs to talk to the world, objects defined in this way are completely understandable mechanistically. The same sequence of commands applied to the same constructor will always yield the same value on query.
But that is, I think, what Monads are supposed to be: things that bind commands into sequences and allow inspection at points in the sequence. As stated in this post’s preamble, I’m not fully confident of this, and may be over-applying an analogy to replace a thing I don’t understand with the comfort of the thing I do. I’d be interested in hearing informed critique on the argument.
Not the other monads
[*] An analogy already present in the proceedings of _that_ 1968 NATO conference, and drawn to extremes by Brad Cox in Object-Oriented Programming: An Evolutionary Approach.
The discussion among my monadically-inclined friends on Facebook indicates that this analogy is incomplete. Yes, monads can be used like that, but they need not be used like that. Counter-examples included the reverse state monad in which state flows backwards, and the TARDIS monad in which state can flow in both directions.