next :: Stream a -> IO a
The function part is pure. The `execution` of the resulting `IO a` action (which is completely separate from its pure evaluation) is not.This is not true. The arguments for `next` include both:
* The target stream.
* A "state token" or universe.
You get different results with different state tokens.
At a high level, the thing to consider is that we can model all imperative programming with functional programming -- we can model Turing Machines with Lambda Calculus -- as well as go the other way around, because Turing Machines and the Lambda Calculus are, for all intents and purposes, equivalently expressive.
Modeling IO with state monads isn't a hack; it's the point.
Can you replay a get from stream by passing in an older token?
Monads provide a way to combine them and a way to inject values into them; but not all monads provide the inspection interface that would allow you to examine that state token. The definition of a monad guarantees only the injection and the combination (the "unit" and "multiply").
You can perceive yourself moment ago exactly because of that.
Others who have not seen you recently hold the old reference to you.
I would rather say that the world is naturally immutable.
That's not how IO in Haskell works, you're basically describing what Haskell would be if it literally had no side-effects ever.