There's a misunderstanding at work here about how Haskell actually regards side effects. In a few words: It provides an API for declaring side effects, and forces you to use this API when chaining them together, but it does not refuse to acknowledge their existence.
Haskell's reputation exaggerates how this API was less powerful, or missing altogether, in early versions of the language. But its reputation is not what you write programs in.