How does Haskell deal with things like memory-mapped I/O or signal handlers where the value of a variable can be changed by factors outside of the programmer's control?
IORefs usually, which can only be manipulated within the IO monad, so they tend to only get used at the top level and passed down to pure functions as parameters.