
On Sat, Oct 27, 2012 at 8:48 PM, Shachaf Ben-Kiki
On Fri, Oct 26, 2012 at 8:23 PM, Brandon Simmons
wrote: 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.
To (1), it's probably worth mentioning the idiom of pre-applying readTChan and writeTChan to a channel to produce values of types "STM a" and "a -> STM ()", which gives you something pretty similar to read-only and write-only channels. It doesn't solve every problem, but for many things it's much simpler than introducing special-purpose types that only ever have one operation applied to them (similarly you could use values "STM (STM a)" with dupTChan/newBroadcastTChan, and so on).
Shachaf
Ah! I use that myself in a library because it let me create Functor and Contravariant instances for the read and write ends respectively, and I didn't require any additional operations beyond read and write.