That functions are pure means that their inputs and outputs are well defined, not that they ignore or don't work with things like state or time.
Before monads were 'invented' for functional programming, reactive programming (or stream based I/O) was the only way of handling state and side effects in Haskell.
Before monads were 'invented' for functional programming, reactive programming (or stream based I/O) was the only way of handling state and side effects in Haskell.