Hacker News new | ask | show | jobs
by gmfawcett 2956 days ago
Monadic I/O (as I'm sure you know) just means that every I/O effect takes a world-state as an implicit parameter ("the world just before this action"), and returns a world-state ("the world just after this action") to thread into the next effect. In a concurrent program, I/O effects from multiple threads (and the outside world) may be interleaved or executed concurrently. Crudely, the world you changed a moment ago isn't necessarily the world you're about to change again. :)

Monadic I/O on its own doesn't make any guarantees, or impose any requirements, about locking external resources. If stdout is locked (from within the monad, or not), then that's the state the world arrives in for your effect. If not, then it's not. They are orthogonal concerns.

1 comments

I get what you're saying, but I don't like to think of these as orthogonal: locking is a way to force actions to occur in a particular order, so is monadic IO (the 'world-state' is a dummy data dependency, preventing later actions from getting called before earlier ones; it doesn't "really" contain the whole state of the world ;) )
I get what you're saying too. :) I think one reasonable semantics for monadic I/O is that it sequences effects in a single thread; and effects from other threads are part of the world-state, not part of the monadic context. Another reasonable semantics is what I think you're describing: monadic I/O in a multithreaded program should sequence effects across all the threads (e.g., mutexes on shared resources). It would be nice to have both options available -- maybe similar to how you can plug a strategy into Haskell's Control.Parallel.Strategies monad.

https://hackage.haskell.org/package/parallel-3.2.1.1/docs/Co...