
Robin Green wrote:
I have been thinking about to what extent you could cleanly do I/O without explicit use of the I/O monad, and without uniqueness types
Here's a way to see I/O as a pure functional data structure. To keep things simple, we model only Char I/O: data Program = Quit | Output Char Program | Input (Char -> Program) -- ... add here other I/O primitives if you want -- Example: cat :: Program cat = Input (\c -> Output c cat) -- Trivial mapping into the IO monad runProgram :: Program -> IO () runProgram Quit = return () runProgram (Output c p) = putChar c >> runProgram p runProgram (Input k) = getChar >>= runProgram . k Another approach could be to use lazy I/O, à la interact. However, I am uncomfortable with lazy I/O. See also IOSpec, a nice functional model of the IO monad: http://www.cs.nott.ac.uk/~wss/repos/IOSpec/ Regards, Zun.