Like a lot of people, I've been getting on the Haskell train. It's not an easy train to ride, the language is very different from anything I've studied since university. Yeah, they gave me the Scheme intro class, but since I had one of those "practical" degrees in "Computer Business Engineering" (you know, a boatload of accounting plus languages business supposedly used in 1988, like COBOL), most of that knowledge has completely faded away. So I've been reading all of these explanations about monads and I'm still not getting it. What are they for?
More to the point, are monads something mere mortals are supposed to write? Very few times in my life have been called upon to write a data structure, like a hash or a tree-- 99% of the time those are features of a standard library, and I have only had to use them to get done what I wanted done. The few times I did write one, it was in the practice of some high dark art-- massive data compression of archival streams, for example-- and not the day-to-day programming most developers care about, the gluing together of features to get something practical done. I suspect that, even if I understood monads as well as I do data structures (and I do understand them), I wouldn't have much use for them. It's a bit like trying to grok the Y-combinator: I'm impressed that it works, but I don't know how to practically apply it in real life, and it expresses a level of abstraction that, for me, is still more alien than not.
That said, there is one issue in all the lectures on monads that I did finally grok, and I want to share it, without falling into the trap of writing a monad tutorial. For imperative programmers (and OO is an imperative paradigm, just one with pretty wrapping paper), all functions are producers, consumers, connectors or transformers. (They can be one or more of these, although I conted that any function that is more than one is broken.) Functions do something: they produce content to be consumed, they connect producers to consumers, or they transform produced data into a different form: filtered, mapped, cross-produced, whatever.
In functional languages, functions are something. They get passed around, their content expressing something. But here's the thing: at the end of the day, they're just something for another function to use. They are something in the same way a function is something. Therefore, they need not be tranformative. They can just be, and you don't have to worry about what they're being, so long as the signature is correct, in the same sense that you don't have to care what a value is, so long as the type is correct. This is a huge mental hurdle for imperative programmers, who expect functions to do something rather than to _be _something. Unfortunately, all of the essays from the functional side about learning Haskell, or Clojure, or Scala, ignore this point, mostly I suspect because the people writing them have mastered functional programming and forgotten all about this hurdle. Once you get past it there are other hurdles, but that one is high, and worth getting over explicitly.
I'm sure I'll understand all this eventually.