I'm more or less a novice with FP, yet to learn a language more functional then Python, but this, and the article, are along the lines of something I was thinking of. Why exactly is it that I/O is stateful? A program, after all, is something that takes in input and spits out output, right? Why can't it be:
[Byte] -> [Byte]
main [data:rest] = ...
(sorry if I'm making up syntax or types, haven't properly learned Haskell yet). Well, my friends tell me, the problem is that often times you have to deal with timing, exceptions, etc. Well, fine:
[(Byte, Integer, Error)] -> [Byte]
main [(data, time, err):rest] = ...
As you said, no reason actual evaluation has to correspond to the logical order of evaluation.