
My own perspective on monads is this: In procedural and OO languages, when dealing with compound data structures, we think in terms of getters (*taking data out* of the structure) and setters (*putting data in* to the structure). Languages with some impure functional features (Lisp, Scheme, Perl, Python) let you operate on lists with a "map" function ("mapcar" in Common Lisp), where instead of *taking data out* of a list, you *put a function in*, and the function manipulates each element without being aware of the context. You *turn the data structure inside-out*, as it were, so you don't have to think about how the elements are accessed. Functors are a generalization from lists to "things that can be mapped over" in general, and then monads are a generalization of functors. Haskell solves the "how can I do I/O in a pure functional language" problem by *turning the world inside-out*. Instead of taking data from the mutable outside world, using functions to manipulate it, and depositing results back into that world, you put your functions into the IO monad. It's like the joke about how a theoretical mathematician catches an elephant: build a cage, go inside, close the door, and redefine outside as inside.