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"... :) )
This is, arguably, the biggest reason to use Monads in the first place, the typeclass thing.
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.
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"... :) )