As codygman mentions the IO Monad doesn't make haskell impure.
unsafePerformIO :: IO a -> a on the other hand does make haskell impure when it is used. And it is used in many libraries.
> unsafePerformIO :: IO a -> a on the other hand does make haskell impure when it is used. And it is used in many libraries.
Hmm, does it really? Is 'unsafePerformIO (return 1)' impure?
"And it is used in many libraries."
Citation needed - or at least clarification as to what "many" means here.
I don't think I'd call the IO monad "dirty" since it's still pure. Also "dirty" make it sounds like a hack.
Pure manipulation of values describing impure computation.
To further answer your question, "functional programming" isn't always so well-defined. We know, realistically, that pure functional programming isn't going to work for all use cases. Once you're grounded in FP, you think of mutable state (or, in databases, destructive updates and deletes) as an optimization... but sometimes it's an optimization that you need. No language is FP-only because no language can be; even Haskell has the "dirty" IO monad.
I think that most good programmers (like, 99%) recognize the importance of immutability and referential transparency, when possible, and in the function rather than the action being the standard compositional unit for programs. Where there is disagreement is on when, how, and how often to depart from the functional ideal.