This here is a brain dump of the way I want to some day get around to offering another take on teaching Monads. I cannot say that I understand them as well as I should, but I think I at least understand how people like myself don't learn them.

A principled tutorial from Tony Morris (don't let that turn you off).

A presentation I like (the audio sucks, though): Databases are Categories, care of Galois.

To wit, from the perspective of somebody who does Java as a day-job:

  • Monads probably aren't even really something you need to know to get by in your day-job. Some folks might be sad with that state of affairs in the world, or say that I'm outright wrong. But I think the history of monads in programming is really not from a Java imperative background, so it can seem a really rather pointlessly esoteric topic at all.
  • They first appeared to be useful in things like Haskell, but turn out to not be entirely stupid even in less pure-fp languages.
  • Monads are a flexible concept because they only require a few things to qualify as a monad, and so people have found a range of things that can thus qualify. One common basic idea is that of a "container". Another is that of "holding state" as in mutation. I expect there are others.
  • Since they are an abstraction, and can represent a range of more concrete things (Lists, I/O as we said), it turns out one can then make tools that understand the monad abstraction and not the concrete stuff, and yet be able to apply those to the concrete stuff. In other words, you suddenly get some cool powers kind of for free.
  • Know that monads are not all that unique. There are lots of other things that are relatives of monads, with their own useful uses. For some reason it just turns out that monads have the best PR / lobbyists / agents. Point being that getting all hung up on monads monads monads like Ballmer is (a) making it harder to understand them because they seem like rare unique strage single-instance things never to be repeated on earth or in heaven and (b) just parochial, mathematically speaking.
  • Don't use the usual names for things, I think, since they are not really couched in Java coding style, they are entirely too much from the math side and are utterly confusing at first cf. "return". (To bolster my opinion, I'll point out that the F# people figured the classic names were a little daunting.)
  • Show Java-style pseudo code for monads. (See below with the Scala and Haskell progression.) Fake whatever notation one would need e.g. higher-kinded types. Just bung out the interface so people can see it. This will not give them a real idea of what they are, but it can help start to ground things. I believe we have to move from the concrete to the general. Starting with details of the general view (cf. Category Theory) is going to lose the audience.
  • Give examples of the API e.g. List, Option, I/O. Keep them short and sweet, say that they are meant to just show that monads can be and are used in concrete ways.
  • Show - even animate - a progression from the Java style to a Scala style of the same things to a Haskell style of the same things.
    • Java-ish:
      	public interface IMonad<T<_>>
      	{
      		T<X> wrapData<X>( X x );
      		Function<T<X>, T<Y>> wrapFunction( Fuction<X, T<Y>> fn );
      	}
      	
    • Scala-ish:
      	trait Monad[T[_]]
      	{
      		def wrapData[X]( x:X ) : T[X]
      		def wrapFunction[X, Y]( f : X => T[Y] ) : (T[X] => T[Y])
      	}
      	
    • Haskell-ish:
      	class Monad m where
      		wrapFunction :: m a -> (a -> m b) -> m b
      		wrapData :: a -> m a
      	
  • Leave the Category Theory side of things last, or as a side-bar that links to longer discourse. Don't really mention it too much at all here, just keep it about code.
  • Now kick in abstraction. Have a pseudo-code working example and run with it. You have to interactively extend a simple example to show the nature of monads. This is all about teaching and understanding via behaviour over data (which is actually always contentious).