
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 (which are the main alternative to monads in pure functional programming, and are used in the Concurrent Clean programming language). Suppose you have a main event handler function, like this: eventMain :: (Event, SystemState AppState) -> (Command, SystemState AppState) This function could be called over and over in an event loop, until an EndProgram command was received, and the event loop would itself do all the actual I/O (the SystemStates are only in-memory representations of some part of the system state, plus the application's own state). Things like disk I/O could be done with commands which generate events when complete. Interprocess communication could be done in the same way. Then eventMain, and everything called by it, would be referentially-transparent, and yet non-monadic. You could of course build higher-level stuff on top of that. On the other hand, it's quite stateful, because anything you need to remember between events need to be recorded, either in the SystemState or externally (e.g. in a file). I suppose this is the most important disadvantage? Is there any published work or code using this approach, or something like it, in a pure functional language? I'm primarily interested in embedded system and desktop UIs, rather than say web-based systems, although both would be interesting. -- Robin