> So the (a, World) result isnt fully deterministic from World. Even if you make each IO operation atomic, a chain of IO is still impure because the final (a, World) result depends on mutations introduced during execution.
It is fully deterministic from World but you cannot possibly describe a World so you can't supply it nor replicate it.
> So Haskell is "pure" when it comes to IO, but not in the way anyone except overly pedantic people mean the term.
You can't create a World so it is pedantic in that fashion but you are able to think of the functions as pure otherwise making integration easier.
A simple example is that IO happens in the correct order in Haskell because of the evaluation order not due to some external construct ensuring that lazy doesn't bite you.
Thats my best attempt, and it still sucks! I bet someone will start wondering about the uncertainty principle there... So lets just use a free monad or thunks in a strict language
function pureAction() {
return function() { return impureAction(); }
}
function chain(pureAction, fnReturningOtherAction) {
return function() {
var impureResult = pureAction();
var newAction = fnReturningOtherAction(impureResult);
return newAction();
}
}
function interpreter(mainAction) { return mainAction(); }
Everything is pure, since all the functions don't do anything but return thunks for the interpreter to run. Except the interpreter which actually runs those. This isn't even a theoretical explanation - its exactly how PureScript's Eff works.
The lift to constructing an IO program from a Haskell type is pure, but the execution of that program to generate a value or effect on the system is not.
So Haskell is "pure" when it comes to IO, but not in the way anyone except overly pedantic people mean the term.