Monad Description For Imperative Programmer

This is about to put a definition/description to test. So please cooperate!
;)
Is this a useful – sufficient, not complete – definition/description for a
monad; for an imperative mind: (?)

"A monad is like a loop that can run a new function against it's variable in
each iteration."

(I insist on the simplicity! And I will resist any expansion of this
sentence (except for an exceptional note that I think of it hardly).
I think there is not any complete definitions in computer world. At least
there are many things to know when you want to use them in practice. So
please have this in mind and review me!)

Cheers :)

Note:
This is not correct in the context of Haskell. (Alexis Hazell mentioned it on haskell-cafe to me)

But I meant in (for instance) the context of C# , for a C# programmer,
who have not any Haskell knowledge.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Spin

I think I agree with your analogy but I would put it this way. There are two types of functions. Pure functions return one output for one input. "Monads" or functions with more than one state may return more than one answer depending on the state. It is the difference between one answer and many answers. A system with a "monad" is a multi-valued system that returns multiple answers for one input query or hypothesis.

One that can return multiple

One that can return multiple answers. The identity monad's valid, as is the one that just sends everything to _|_.

Is that an agreement or a

Is that an agreement or a disagreement?

My original statement doesn't cover all the cases. You might have several answers for a given query, different answers for the same query depending on a state, etc. I have in mind a decomposed automata description where each partition has one state if possible, otherwise more than one. The single state partitions correspond to pure functions. This seems like a complete picture of a computation and therefore it should correspond to the monad view of a system. Yes. No. would really like to get to the bottom of this.

Apparently a reading error

Apparently a reading error on my part :-) We appear to be agreeing violently - still, quirky monad examples're useful to have around.

Yea!

Yea! Yea!

it's --> its

And maybe it's because I'm not English, but I don't find your definition simple, Hank Thediek's definition seems more easy to understand.

That said, I must admit that I don't really understand monads..
I approximate a monadic function as 'stateful function' compared to mathematical functions which are stateless, so a monad is what associate a 'stateless function' to a 'stateful function' but I could be 100% wrong.

I know what you mean, but

I know what you mean, but I find the term 'loop' slightly misleading from the point of view of a C#/Java/C++ programmer.

Also, I don't think of monads as loops, or sequences. They can be used for sequencing. Perhaps you want to say something like 'A monadic computation...'

If I had to give a naive, incomplete definition, I'd probably prefer 'a strategy for performing chains of computations'.

What do you want to achieve with the definition? If I was a C# programmer without Haskell knowledge I'd rather want to know/understand what's the big deal about monads. From a C# mind, iteratively applying functions to a value - big deal. But you might know your target audience better than I do.

Well, maybe he wants to make

Well, maybe he wants to make an introduction to Monads for 'imperative' programmers which doesn't start by "in the category theory", a sure way to loose the reader..

Where do I mention category

Where do I mention category theory? (Really curious now because I know only very little of CT) I didn't even start 'A monad is a type constructor ...'.

Another way to lose readers is to make it so simple that you make them believe it's just a crutch to be able to do in a pure functional language what you can do in an imperative one any time of the day. I just think that sequencing is one of the less interesting things about monads, and I say that as a long long time imperative programmer.

I'd say that the structure's

I'd say that the structure's support for sequencing is pretty fundamental - but the number of different notions of sequencing you can work with is much more interesting! State, Reader and List all behave rather differently.

Exactly

Just what I meant. When I said 'less interesting' I did not mean to imply it's not important or a minor aspect.

I think most of the other

I think most of the other things that're interesting about monads apply to things like Arrows and Applicative Functors too (they support sequencing too though, just not in a way that by default allows higher-order computations the way monads do).

Why understand Monads?

For me personally, the impact of grasping monads is somewhat comparable to the impact exterior calculus had on my grasp of standard calculus, vector calculus and topology.

If you grasp the "integral of differential of a form over a surface = value of the form over the boundary of the surface", you've just understood the divergence theorem ("integral of divergence of a field over a volume = flux of the field through the surface bounding the volume") and the curl theorem ("flux of the curl of a field through a surface = integral of the field over the boundary of the surface"). Why, even the one dimensional integral theorem is a special case of that in exterior calculus.

Similarly as a programmer I've been working with lists, sets, sequences of computations, parsers, IO, etc. for quite a while and after encountering monads, realize that they are all fundamentally the same in nature.

You're shooting for simplicity, but the effort in grasping the complex applications of the monad concept is well worth it. Your thinking changes forever.

Perfect

Analogizing something I can manipulate mechanically but can't say I understand with other stuff I can manipulate mechanically but can't say I understand. This does not bode well...

My understanding of Monads

As an imperative programmer for many, many years - this is my understanding of Monads:

A monad is the (minimal) construct that is used to create imperative code in a way that uses only pure expressions.

ADT's

A monad is an abstract data type.

Analogy

To know an analogy is not the same as to understand; I know.
But to have a precise analogy; is the same to have a good starting point; and when you have a good starting point, the way before you would be more fertile.
And Yes! Monad is a ADT. But monad "is" something and "means" a lot of things (a pattern of patterns); So if I say monad is an ADT, it does not help so much.
It is more useful to feel the aspects, over knowing the meanings.
Thanks

Imperative understanding right direction?

Is trying to understand monads from an imperative point of view a good idea? Even if I want to emulate the 'functional style' of programming in an imperative environment, I really have to understand functional programming on its own terms (pun intended). Forming analogies like 'a function is like a procedure' or 'having first class functions is like passing pointers to functions' sends one in the wrong direction. For me, I'll be satisfied that I 'get' monads, when I can read one of Wadler's papers and extrapolate from his examples to my own problems. Not there yet.

There is no single 'right' direction

My early introduction to OO style was very frustrating, with the magic of inheritance, then I read 'how' it was implemented which allowed me to understand it better and then I read OOSC from B. Meyer and I understood 'why': I doubt I would have been receptive to the 'why' until I've read 'how'.
Other couldn't care less about the implementation details: to each his own.

[And no, I don't 'truly' understand monad but the 'imperative view' is good enough for me]

Monads for parsing

Personally I like Peyton Jones's explanation:
(for example, check out slides 67 onwards for IO monad diagrams)

Consider the problem of writing a parser in a purely functional language. You have a list of characters or tokens, and a "pointer" into the list where the next token is read. A straightforward method of parsing is recursive descent, in other words recursing down when you see a token marking the beginning of an expression and back up again when you find the end of the expression.

In an imperative language you can write this easily, using a mutable variable to increment the pointer after "eating" a token. But in a pure language, you can't modify variables, so you must pass the current pointer down the and return the new pointer back up. This is very inconvenient since every recursive call must rebind the new pointer variable.

So instead of writing:

expect("(")
parse_expr()
expect(")")

You would have to write:

let p1 = expect(p, "(") in
let p2 = parse_expr(p1) in
expect(p2, ")")

Monads allow you to pass along this "extra" hidden state without the user having to worry about passing and returning it.

Another example is pseudorandom number generation (which is explained very nicely in SICP). You start with a "seed" from which you derive a seemingly random sequence of values. In a pure language you would have to pass the "current seed" around the whole program and remember to return it so the rest of the program can get the next seed.

In Haskell, this effect is used to enforce sequencing of I/O operations (since lazy evaluation has uninituitive and unrealiable evaluation order) even though there might not be any extra hidden state to pass around since the work is done by the operating system imperatively.

I'm just trying to

I'm just trying to understand Monads this week and discovered this thread. Please correct me if I got anything wrong.

I find the description "a strategy for performing chains of computations" doesn't help much in understanding what monad is. Function composition is also a strategy for performing chains of computations, but it's not monad. The heart of the question is: what's so special about this monadic strategy.

From the operational point of view, as many have pointed out above, monad allows the encoding of hidden states (i.e. the context) which can be passed implicitly along and updated down the chain of function executions. Thus, it achieves information hiding and modularization. Monads isn't unlike objects! I think that's where the ADT analogy comes in.

So, I think a possible explanation to an OOP programmer is: Monad is just like Object which can hide its internal mutable state; and this is very significant because pure functional programming doesn't allow mutable states.

Actually functions and

Actually functions and function composition do form a monad (specifically, the identity monad). Hope that helps!

Oh... Ok, i need to read up

Oh...

Ok, i need to read up on Identity monad. Thx.

No the question is not

No the question is not "what's so special.." but rather "what's so general..". Monads doesn't do any specific thing, but is more of an implementation method that can be used for well, nearly everything.

Monads and mutable state

Monad is just like Object which can hide its internal mutable state

While it is true that some specific monads can be used to hide internal mutable state (for some sense of 'hide', 'internal', 'mutable' and 'state'), there is no necessary connection between monads and mutable state. For example there is no mutable state associated with the list, continuation, probability, Identity, Maybe and Reader monads.

Monads are an abstraction that capture a design pattern. It's a common design pattern that appears in many different contexts. But don't confuse the specific applications with monads in general.

There is (except perhaps in

There is (except perhaps in cases like Identity) something that smells a lot like the state of an abstract machine associated with monads as used in Haskell though.

I'm not sure I see what you mean...

...but I think that this 'smell' might be a trivial observation. There are many types that are instances of Monad. All instances of Monad share a common interface (return and >>=) and (are supposed to) exhibit the monad laws. Therefore, given your favourite Monad m, then any other random Monad, m', is going to have similarities to m, and appear to justify the view that all Monads are like m.

Hence we have people who think that Monads are about sequencing, state, computations and so on.

But a properly 'Copernican' view would be that all of these things have something in common, but no one is more fundamental than the others.

Identity is a rather

Identity is a rather specific case though - Derek and I found a couple more examples kicking the idea around on IRC (both variations on the Const monad where everything gets sent to the same value). But we didn't find any non-trivial monads it made no sense at all for, the big change to the model was that rather than adding state to the machine it's modifying it - List clones/branches it, Identity leaves it untouched, Const eliminates it.

machine states vs. mutable state

There is (except perhaps in cases like Identity) something that smells a lot like the state of an abstract machine associated with monads as used in Haskell though.

Of course any monadic computation can be expressed as an abstract machine, but that doesn't automatically correspond to mutable state (which is what sigfpe was talking about). For example, a monadic model of a pure lambda calculus evaluator might use an environment monad, but there's no mutable state there.

OK, so i got it wrong that

OK, so i got it wrong that having internal state is a defining characteristics of monad. But, Maybe monad, doesn't it hide the error/fail state so that the error state can be "propagate up" implicitly?

I re-read the monad stuff

I re-read the monad stuff (in Haskell). Please correct me if I got any of the following things wrong:

At its minimal,
1. An instance of Monad is a type constructor
2. It needs to define at least the (>>=) operator
3. and the return functions.

To me, I can easily relate these to
1. An ADT (or object) constructor
2. a "wrap" method
3. an "unbox" method. (as in C#)

Hence, i got the "is just like Object" analogy.

What is the sound of one monad clapping?

As others in this thread have intimated, one of the reasons there are so many "what is a monad?" threads is that monads are a very general idea with many specific uses that unfortunately all go by the same name as the general one.

Imagine if you will a world where monoids, linear grammars, regular expressions (as a general concept) and the specific notation of Perl regular expressions were all referred to as "monoids" and you would have a rough analogy.

We take it for granted that each of these things can be understood independently, and that it requires a lot of thought and study to see how they are related. This is made easier by the distinct terminology.

With monads, when you ask "What is the essence of monads?" you get very confusing responses because the term "monad" is used indiscriminately to describe a very general mathematical structure rooted in Category Theory, a theoretical PLT concept based on the former, but with a strong functional programming grounding, as well as particular constructs implemented in particular languages, most notably Haskell.

Unless you know which one your interested in, it is hard to give a pithy explanation to suit your purposes.

Furthermore, someone who has never programmed in an FP language will probably not appreciate either of the latter two uses of the term.

For this reason, trying to explain monads to "imperative programmers" (i.e. people unwilling to learn an FP language or spend the time on the theory) is probably a waste of time.

It's worth bearing in mind

It's worth bearing in mind that Haskell's idea of a monad is an instance of the PLT concept and the mathematical structure - even if (sometimes aggravatingly) the Monad typeclass doesn't capture all possible instances in Haskell. The addition of >>= is perhaps a little more confusing.

Philippa, what do you mean

Philippa, what do you mean by "The addition of >>= is perhaps a little more confusing"?

The categorical definition

The categorical definition uses the equivalents of fmap and join instead - you can define >>= in terms of fmap and join, and you can define fmap and join in terms of >>=.

Monads for the masses

But wouldn't an "imperative programmer" inevitably discover monads when he'd reason about design pattern for generic programming? The basic problem for understanding is IMO the step from a type parameter b to a very general opaque type m b depending on b. You can't spell this in C#, Java or C++. These languages with their template parameters are not expressive enough to give meaning to such a notion. You can't say: "here I hand out a general abstraction of a class depending on two type parameters T and V" but you need a concrete class depending on these type parameters.

Of course the monadic definition contains an element of functional programming since it defines machinery for restoring function composition for functions f : a -> m b. Once the programmer sees that this machinery is available and gained even syntactical support she will look for use cases and those give the impression of arbitrariness ( because there is one for each type class m ). FP is not really the hurdle for proper understanding.

If a language ( god beware us of C++ ) would start dealing with class abstractions and consider classes with type parameters as instantiations of metaclasses with type parameters we had sooner or later monads for the masses ( maybe Haskell will be faster and the masses are programming in Haskell? Fortunately I'm not in language advocation business. )

Monoids for the masses

But wouldn't an "imperative programmer" inevitably discover monads when he'd reason about design pattern for generic programming?

To me this doesn't make any more sense than, to continue my analogy, saying that any programmer who thinks about regular expressions will inevitably discover monoids.

Many people master the former without having an inkling of the latter, or if they have such an inkling, why they are related and why they should care.

FP is not really the hurdle for proper understanding

Without an understanding of accumulator passing (and why you want to do it), or the constraint of statefulness (and what that gives you), I don't think you can have any sensible intuitions about what (PLT) monads are all about.

For an imperative programmer, the easiest way to do what monads do is going to be using unconstrained stateful operations; to understand the motivations for them, you need to have a basic idea about FP, how it works and why you want to use it.

To me this doesn't make any

To me this doesn't make any more sense than, to continue my analogy, saying that any programmer who thinks about regular expressions will inevitably discover monoids.

Right, but there was nothing inductive in my remark. It was you who insisted in the need of lots of concrete intuitions about PLT use cases to understand a very particular algebraic structure. I claimed quite the opposite and said that people have to be accustomed to deal and play with an expressive type system to make sense of particular pattern. Some of them may be important to the needs of purely functional programming. It's easy to see why and there is even syntactical support. So what?

Monad and Continuation

Something has just struck me when I went back to read more on monad. The Haskell syntax:

do x <- e1; e2; e3;...

=> e1 >>= (\x -> do e2; e3;...)

The binding operator takes the first evaluation as the first parameter and the rest of the execution as the 2nd parameter. Isn't this continuation?

So, what's relationship between monad and continuation? Is it just monad provides a way to implement continuation style of chaining?

So, what's relationship

So, what's relationship between monad and continuation?

Incidentally, this paper I was just reading may have your answer. It discusses monadic, continuation-based, and A-normal form-based intermediate languages.

Monads & CPS

So, what's relationship between monad and continuation? Is it just monad provides a way to implement continuation style of chaining?

Monads use continuation-passing style to make control flow explicit. This allows them to enforce sequencing (particularly in a lazy language like Haskell), and also to manipulate control flow in other ways (e.g. the Maybe monad, the Continuation monad).

Monads in the PL context are a kind of generalization of CPS: values passed to continuations in monadic computations are wrapped in an arbitrary container datatype which can contain additional information, and the 'bind' operation provides a datatype-specific hook to unwrap the values in these containers and possibly perform additional operations whenever a continuation is invoked. This is a very general pattern — it's actually a purely functional way to represent interpreters, which is the context in which monads originally arose in PL theory. As a result, the possible applications of monads are very broad.

Having said that, I'd like to suggest that these sort of "help me understand monads" threads are a little offtopic for LtU. There's plenty of material on the web about monads — see the Monad tutorials timeline. Monads are an interesting topic with a lot of relevance to PL theory and practice, but for an initial understanding of them there's no substitute for a bit of studying and writing code using monads in an appropriate language (which practically speaking, probably means Haskell). There's plenty of material on the LtU Getting Started page about these topics.

The PL angle

I've been kind of wondering whether the emphasis on "how useful monads can be" has short-circuited the question of language design? That is, are there ways to design PLs that make monads easier to manipulate and/or easier to learn (or tutorialize)? And is having one generalized way to construct monads better than having language constructs that have specific monads built in (states/worlds, etc...)?

maybe is not just a monad

I've been kind of wondering whether the emphasis on "how useful monads can be" has short-circuited the question of language design?

Perhaps in threads like these. But I doubt that the insatiable desire of programmers to find a problem for every solution is significantly affecting people working in PL research any more than it usually does.

That is, are there ways to design PLs that make monads easier to manipulate and/or easier to learn (or tutorialize)?

Monads provide a kind of balance between rigor and formal simplicity. The relationship between rigor and ease of use is usually an inverse one. Even formal simplicity doesn't necessarily translate into ease of use outside of a (meta)mathematical context — if it did, then the pure untyped lambda calculus would be one of the easiest to use programming languages. I suspect that if you want to retain both properties, that there may not be much room for ease of use improvements when using monads directly.

OTOH, a typical imperative language can be modeled as a monad which carries an environment, a store, and various other bits and pieces (depending on the language). Manipulating this monad is pretty easy: people do it in all the usual imperative languages, all the time. So we already know one way to make monads easier to use. I guess one question is whether there's a useful middle ground between the two approaches, other than what existing languages (e.g. ML) already provide.

And is having one generalized way to construct monads better than having language constructs that have specific monads built in (states/worlds, etc...)?

Maybe having a way to generate DSLs (more specific than do-notation) for specific monads could help.

Formality with Types

There certainly is a PL angle to this discussion. I don't think "imperative" programmers really want to learn Haskel but they do sense something interesting in monads. Haskell is a FORMAL imperative system. We are familiar with formality in functional languages but not in imperative or stateful ones. Imperative systems can be formalized by using systems theory, but there don't seem to be any languages that do this "formally" with "types" like Haskell.

Monads are:

I can't resist taking another stab at this. Monad systems theory is an alternative systems theory based on abstract algebra. This leads to the question: Why do we need an alternative to systems theory especially given the very modern coalgebraic theory of systems. Isn't the monadic theory contained in the coalgebric theory. Hopefully someone knows more about this than I do?

A very simple definition

Here's a defition I posted about a while back:

"A monad is an interpreter mod."

I mean 'mod' in the sense of 'modification', like for a car or a game.
And by 'interpreter', I mean the conceptual central engine that moves
computation forward, even when we're talking about a compiled
language.

This definition ignores the underlying mathematics, or the implementation details, or even the 'user interface' to monadic programming.

The rest of my post is here:

http://lambda-the-ultimate.org/node/1276#comment-14228

sorry i missed this

Interesting. I inadvertently duplicated you, but more verbosely, below. The name "monad" is well chosen -- as in some active entity that has it's own world-line and that is interesting in so far as it "does computing". That's hard to relate to the generally familiar, though.

"Faces or Vases?"
-t

monads for the intuitive imperative programmer

Caveat: this answer to the original question is the one I have in my mind but it hasn't really been vetted by people who know more about these things. So, I'm offering it either to elicit a response like "Yeah, ok" or "Super" or...importantly, "No, that's completely wrong." It's wordy and it only vaguely waves a hand in the direction of important things like monad axioms and composability -- but I think it might be a useful bridge between vocabularies and intuitionistic mental constructs:

A monad is a very abstract kind of "virtual machine".

By a "virtual machine" we mean a simulated CPU, connected to a memory, and also connected to I/O devices. For simplicity, for now, let's just talk about simple, serial VM's -- they run one "virtual instruction" after another. Each instruction gets to update memory, read from the I/O bus, and write to the I/O bus. (The "virtual I/O bus" and the "virtual memory bus" are very similar -- the main distinction is that the I/O bus connects to "external things" whereas the memory bus is, in some system specific way, "private".)

Think of how to define a new virtual machine instruction: you have to describe some function that takes the state of the I/O bus and the state of memory as input, and as output the instrution-function tells you how to update memory and what signals to put on the I/O bus.

You're probably used to the idea, common in many popular virtual machines, that the set of instructions is both fixed and finite. It's "fixed" because they VM comes with some list of instructions and those are all there is. It's "finite" because, more or less, each instruction is defined as a "finite state machine" -- a "jump" instruction just moves a value from memory into the PC, an "add" instruction takes values from two registers, passes them through an adder, and stores the result in a register. This kind of finite instruction is limited in computational power but you can implement these kinds of instructions very efficiently.

Well, suppose instead we did something radical and created a virtual machine where programmers could add new instructions, and those new instructions don't have to be finite state machines -- they can be *any* computable function. So, instead of an instruction like "push 5 on the stack" you could have a single instruction like "pop an arbitrarilly long list, sort it, and push the result" or a single instruction like "pop a chess position, run a minimax algorithm, compute the best-guess next move, and put the result on the I/O bus."

So: a mondad is a kind of virtual machine in which you mostly program by defining new instructions and, to define new instructions, you can write pretty arbitrary, very high level functions. We don't care that these instructions won't run in a single, real-time "cycle" -- we just like to organize our programs this way.

The real power of programming by adding instructions to virtual machines happens when we realize that it's often convenient to define a really complicated virtual machine in terms of a "circuit" of simpler virtual machines, connected by their I/O busses and/or by shared memory, until at the bottom of breaking down the problem this way we arrive, eventually, at VMs with very simple instruction sets -- VMs that a compiler can implement directly and efficiently.

Designing an "API" for creating VMs and adding instructions to them is a subtle business. Naive ways of doing it can be useful, but what the language researchers are in the middle of discovering are ways to design a very clever API for these high-level VMs. By "clever" I mean that they are making it easy to mix and match code, and glue VMs together smoothly, etc. They are busy working out these APIs as a kind of "algebra" so that you can describe a circuit of these abstract VMs about as easily as you can write an arithmetic expression -- at least once you get the concepts of the VMs in your expressions as well as you get numbers in arithmetic.

It may sound hopeless hairy and geeky to think we should be programming by describing circuits of abstract VMs with fantasy instruction sets, yet, the people who are actually trying this approach are finding that it often works out very simply, efficiently, and robustly in practice. It's an abstraction that is a good "fit" for how software can be effectively designed and implemented. It gives us a definition of a "module" (e.g., an instruction set, or a particular circuit of VMs) where that definition of module just seems to work out very nicely in terms of division of labor, proving correctness, and similar concerns of group engineering efforts.

-t

reflective programming

I like this way of looking at it too -- a custom VM and a custom interpreter are similar, differing mostly in the hypothetical implementation details.

Monad as Curried Interpreter

'bind' and 'return' are analagous to function application and constants/variables.

'bind' is a way of applying one expression to another, although in reality it passes the result of a computation to another computation, and perhaps does other things like threading state.

'return' simply injects a value into the monad, which is like a constant or variable expression. I'm thinking of lambda expressions as constants. Also, I know in the strict lambda calculus, you don't have a variable reference and an environment -- the variable reference is just replaced by the value it was bound to.

This is what prompted me to think of a monad as a sort of stripped-down lambda calculus interpreter object. It has the two main operations, and by writing 'bind' and 'return', you implement those two operations.

Monads and substitution

Monads are often related to substitution in computer science uses and this is robust. You do indeed get that return labels a "variable" and bind applies a "substitution" (function) to the "variables" (hence the name "bind".) This comes up again for algebraic uses/free monads.

Sort of...

> A monad is a very abstract kind of "virtual machine".


There are two sides to every metaphor. There are the things that a metaphor is apt for, but there are also the things that it's not. You have to choose your metaphors to get both sides right. Your description fits some kinds of monad very well. But the catch is that it also fits comonads, applicatives, Arrows and probably lots of other type classes too. So what's missing here is any kind of discussion of what aspect is specific to monads. (This complaint is true of many other metaphorical descriptions of monads - it reminds me of the Wason test.)

The combination of both a

The combination of both a (potentially trivial) notion of sequencing and higher-order computations. Arrows with application also offer that, but they're equivalent to monads.

seeing beyond the literal question

"... the catch is that it also fits comonads, applicatives, Arrows and probably lots of other type classes too. So what's missing here is any kind of discussion of what aspect is specific to monads."

For the literal question "What is a monad?", I guess you're right. But my guess is that many of the people who ask that question don't really mean it to be that specific. That is, if there are slight generalizations (Arrows?) or duals (comonads?) of a monad, which can be used for analogous purposes in related situations, they (ok, we) would like to know a bit more about them, too. Which makes the analogy pretty apt, IMHO.

...we) would like to know a bit more about them, too.

This table does an awesome job of summarising the hierarchy of generalised notions of function application of which monads form just one branch.

Definitely -- monads have

Definitely -- monads have very specific, very delibarately chosen semantics. The metaphor I'm using is really a response to people who are new to the concept, or even new to functional programming.

They're getting into pure functional programming, they want to set a variable, they find out that you need monads for this, then they find out that monads are very important, and they get stuck wondering what they are and why there are 'monad laws', and just have no idea what to do with them.

THAT is when the simplifying metaphor is most useful.

When I first started reading about monads, I pretty much understood the concept of state threading and the linearity of the 'world state' and so on; but I didn't know why this bind/return structure was needed. It took me a while to realize that bind/return form a tiny functional language of their one -- one whose implementation you have full control over. I wish that had been mentioned explicitly.

STDERR & STDOUT

I've come to think of >>= and | as serving a similar function -- they propogate a portion of the dual output of one function to the singular input of the following one. In this interpretation, STDERR is the world and STDOUT is our space of values. You could also think of the filesystem, not STDERR, as the world -- but talking about STDERR has the advantage of introducing a scoped world, global to the computation but not to all such computations.

If shell pipelining is a special case of monadic techniques, then it would serve as a wonderfully familiar, down to earth example for the imperative programmer.

Shells and Monads

Monadic i/o and UNIX shell programming.

Just remember that this is a picture of one specific monad, not monads in general. (Though, of course, generalisations can be understood by understanding lots of specific examples.)