
OTOH, if you want to do anything useful with any language you have to learn to do IO (and simple IO is tackled early in most languages), and therefore you must deal with Monads. I often wish that Haskell books and tutorials would introduce IO earlier; it is often near the end, in the "advanced" topics (after you've been dazzled/saturated by the magic you can do with list functions and comprehensions, and how easy it is to create abstract datatypes, and write parsers, etc...).
I think the fact that IO and efficient array updates, etc., are all best (to our current knowledge) handled in a pure function language by monads shows the actual underlying complexity that is hidden in many imperative languages. I drew an analogy between a state machine and an object that contained several variables once in a conversation. Vehement denial about an object being at all like a state machine came from the other parties. After much discussion, they conceded that yes an object really was a state machine but they'd never thought about it that way. The human mind is amazing in the level of complexity that it can deal with and the computations it can perform. Hidden complexity in programming languages however has led to numerous software problems that are common throughout the industry. I just completed a project (with several others) that takes C code and crudely converts it into it's functional equivalent. The next step is to convert the output in a pseudo-language into true functional code. The number of side effects to deal with from some of the simplest expressions has been staggering. Most of the effort in the project was spent on the increment/decrement operators and switch and loop statements. Don't worry, there won't be a c2h (C -> Haskell) anytime soon for those who remember dealing with f2c (Fortran -> C) code, that's not the purpose of this project. On a side note, Stroustroup recently wrote in an article about how the "hello, world" example was starting new C++ programmers down the wrong path from the beginning. He, of course, advocated using the iostreams and then went on to show several examples of wonderful things that could be done with iostreams. Iostreams seem to be closer to a functional concept than then clib printf variations. I think the book, _Structure_and_Interpretation_of_Computer_Programs_, by Abelson and Sussman is a much better freshman text because of it's functional approach. Real solid examples about the dangers of imperative constructs. After years of warping my brain on C++ code, I'm enjoying learning the IO monad. It's starting to make sense at a much deeper level to me. Shawn Garbett