Proposal: split Chan and TChan into read and write ends

wren ng thornton wren at
Sun Oct 28 02:49:29 CET 2012

On 10/27/12 9:06 PM, Brandon Simmons wrote:
> On Sat, Oct 27, 2012 at 8:48 PM, Shachaf Ben-Kiki <shachaf at> wrote:
>> 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).
> 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.

It may be worth mentioning that for this use case there's some beauty in 
leaving it as one type and just giving it two type parameters, a la

     newTChan   :: STM (TChan a a)

     writeTChan :: a -> TChan a b -> STM ()

     readTChan  :: TChan a b -> STM b

     -- aka contramap @(TChan _ c)
     precomposeTChan  :: (a -> b) -> TChan b c -> TChan a c

     -- aka fmap @(TChan a _)
     postcomposeTChan :: (b -> c) -> TChan a b -> TChan a c

since this highlights the fact that the two ends together form a 
profunctor, i.e. a hom-functor which is covariant in its output and 
contravariant in its input.

Of course, even with this representation it's worthwhile to be able to 
abstract over each of the ends in order to preclude reading or writing 
in various parts of your program.

Live well,

More information about the Libraries mailing list