
Hi everybody, Just discovered all the great discussion here, and although my google-fu turned up no prior discussions on this subject, I apologize if it has already been discussed. I propose that Chan and TChan should be implemented as a pair of read and write ends, initialized as follows: newSplitChan :: IO (InChan a, OutChan a) I've implemented this already here: http://hackage.haskell.org/package/chan-split . You can ignore the type classes I've defined; they're there for my own reasons and not part of the proposal. Here is my best defense: 1) My own (and I assume others') use of Chans involves some bits of code which do only reads, and others which do only writes; a split implementation lets us use the type-checker to allocate read or write "permissions" when we pass around either end, and generally makes things easier to reason about. Others have independently reached this conclusion as well. 2) The API is simpler (and in the case of TChans *much* simpler) with a split approach; some examples: in TChan the types of the 'duplicate' functions actually suggest (IMHO) the details of how they treat existing messages, and require a less roundabout explanation dupTChan :: InTChan a -> STM (OutTChan a) cloneTChan :: OutTChan a -> STM (OutTChan a) another example, 'newBroadcastTChan' is actually just: -- | Create a new write end of a TChan. Use dupTChan to get an OutChan that values can be read from. newInTChan :: STM (InTChan a) and doesn't require any explanation beyond that. 3) It's trivial to modify the *Chan libs in this way with a few edits (really, they're already implemented this way, but with some added contortions to return both a read and write end for each operation), so there're no new tricky concurrency issues to reason about. 4) Values written to the write end can be reliably GC'd when readers go away, although recent GHC seems to be able to do this on the current implementation with -O2 on my simple tests. 5) While this is a big API change, I imagine the vast majority of users would only have to change a few type signatures and the Chan initialization action. An `OldChan` module could easily be implemented in terms of the new split version. Alternatively, a *Chan.Split module could be added, and the current Chan module defined in terms of it. So two weeks of discussion? Thanks all, Brandon http://brandon.si