The async callback mess is not really a problem, there is about zillion patterns and libraries to handle it. The problem is error handling in callbacks, capturing stack traces from the async parent callers, and generally not crashing Node if you forget to try/catch your async handler. However, this problem is known, and this is being worked on in the form of "domains". Btw. Iced CoffeeScript doesn't solve this a single bit.
If you have callback hell in your code, it's not because the problem hasn't been solved, but simply that you didn't put the effort to npm install a simple library.
I agree that it is a problem if neglected, but most people don't allow it to be a problem in the first place.
It's like knocking on PHP because it could be used for templating and business logic on the same file. Just because you could, doesn't mean you have to (or should).
I honestly don't feel that it's as big of a problem as people make it out to be. It's simply a minor annoyance. The error handling is the killer.
Could you give a brief code example how monads eliminates the problem of error handling? Do you mean to put try catch in the monad around every async step it takes in? Just the API for how this would even look would be great.
this is just a sketch to give you an idea of what I am talking about.
right well you've probably used jquery before, so the api would look something like this. You start with a sequence of async actions you want to perform.
Now this is a bit different from jQuery since all the methods here do is push method names and arguments onto a stack. it's the .end() method that reads in the stack and goes through and executes it. This means that each method along the way we've constructed a partial computation value- that is, the stack, which we can pass around as a value- just leave off the "end" method...
var scrapeHN = $(ctx).geturl("http://example.com).parseExample().renderTemplate();
now we can modify the computation by turning it into an error handling monad...
var ecm = ErrorCatchingMonad(scrapeHN, errorCallback);
this wraps each method in the monad with a try catch block, and calls the callback if an error gets thrown, and stops the chain from getting executed further. in fact this is how the origial monad was created
var $ = DeferringMonad(scrapingAPI);
which takes a normal jquery style plugin interface/chaining api and turns it into that deferring stack type api with an end(); method.
real answer: It's easy and fun to whine about things you don't get in a language/paradigm you don't know. So easy and fun in fact that's almost entirely what programmers talk about to each-other. But whining hardly gets anything done, does it. The answer is: It's not a problem if you know what you're doing. And that applies to all other instances of this programmer discourse pattern.