The channels are implemented with MVars and therefore inherit all the
caveats that apply to MVars (possibility of races, deadlocks etc). The
stm (software transactional memory) library has a more robust implementation
of channels called TChans.

Operations

Read the next value from the Chan. Blocks when the channel is empty. Since
the read end of a channel is an MVar, this operation inherits fairness
guarantees of MVars (e.g. threads blocked in this operation are woken up in
FIFO order).

Throws BlockedIndefinitelyOnMVar when the channel is empty and no other
thread holds a reference to the channel.

Duplicate a Chan: the duplicate channel begins empty, but data written to
either channel from then on will be available from both. Hence this creates
a kind of broadcast channel, where data written by anyone is seen by
everyone else.

(Note that a duplicated channel is not equal to its original.
So: fmap (c /=) $ dupChan c returns True for all c.)