Learn You a Haskell for Great Good
learnyouahaskell.com
learnyouahaskell.com
Personally I don't find these artsy trendy programming guides that appealing, but if it gets the job done...
(At least, that's why they appeal to me...)
I haven't attempted Haskell enough times for the Monads thing to click, this looks like it might be different enough to jolt it into me. :)
1) Witty, offbeat humor (w/ +1 for cartoons) 2) Interesting examples tackled 3) Restructuring the lesson to work for people who have learning styles unappreciated by typical tutorials.
I'm seeing routine examples like summing recursively/with foldr and implementing linked lists all within an outline not so different from any other Haskell tutorial.
Of course, the real acid test is seeing what zany metaphor the author thinks up to describe monads with.
I found it most helpful to think of monads as being similar to the pipe operator in Unix, but one that has a hook function it calls as it passes results along.
Also, the IO monad is probably the worst to start with; it's one of the most complicated. The Maybe monad is much simpler -- Think of a function that takes a function, f, and a second function, next_f. It calls f and grabs the result: if it's an error, then don't bother calling next_f, just return the error; otherwise, call next_f with the result as its argument. You can chain a bunch of Maybes together, and if any of them return an error, the whole chain immediately passes the error to the end. It's like how || (or) short-circuits in other languages, but much more general.
A similar Countdown monad could start with a time and a list of functions to call, then call them in succession, passing along the results, but immediately aborting and returning an error if the chain has exceeded the specified time to run.
The monad is the chaining construct, but you define what it does with the results it passes along.
Because of Haskell's type classes, it's able to recognize that any construct that supports that kind of chaining behavior (among other things) is an instance of the same general construct, and is therefore able to work with them in a common way. That's surprisingly useful, much like when an object's class is a Class object that supports various interfaces for interacting with the OO system itself (A "meta-object protocol").
Haskell makes a big deal of monads because it needs them to do some things in a functionally pure manner, of course. Still, they shouldn't be considered some completely alien by-PhDs-for-PhDs concept. (I remember Simon Peyton-Jones saying he wishes he'd instead named monads "warm fuzzy things"... :) )
You don't even need Monads to have completely functional IO code. Clean's uniqueness types are another method, but you can actually do it with just plain types if you're dedicated.
Oddly, monads just make things easier. Really.