chan-split is a haskell library that is a wrapper around
that separates a Chan into a readable side and
a writable side.
We also provide two other modules:
Data.Cofunctor (because there didn’t seem
to be one anywhere), and
Control.Concurrent.Chan.Class. The latter creates
WritableChan, making the fundamental chan
functions polymorphic, and defining an instance for standard
Chan as well as
MVar (an MVar is a singleton bounded channel, wanna fight about it?).
Having separate read/write sides makes it easier to reason about your code,
supports doing some cool things (defining
instances), and makes more sense (e.g. the function of
in the base library is much easier to
understand as an operation that happens on an
Also I use it in (the coming new, less stupid version of) my module simple-actors.
You can get it with a:
cabal install chan-split
Let’s write the numbers 1 – 10 to the InChan and read them as a stream in the OutChan:
module Main where import Control.Concurrent.Chan.Split import Control.Concurrent(forkIO) main = do -- Instead of a single Chan, we initialize a pair of (InChan,OutChan) (inC,outC) <- newSplitChan -- fork a writer on the InChan forkIO $ writeStuffTo inC [1..10] -- read from the OutChan in the main thread: getStuffOutOf outC >>= mapM_ print . take 10
And we’ll make
getStuffOutOf, simply be the standard
functions. Note that
writeListToChan is actually polymorphic.
writeStuffTo :: InChan Int -> [Int] -> IO () writeStuffTo = writeList2Chan getStuffOutOf :: OutChan Int -> IO [Int] getStuffOutOf = getChanContents
Now I’ll demonstrate the use of our Functor and Cofunctor instances by re- defining those two functions above, after importing our Cofunctor class
import Data.Cofunctor ... -- we could convert the [Int] to [String] here but will instead demonstrate the -- Cofmap instance: writeStuffTo :: InChan String -> [Int] -> IO () writeStuffTo = writeList2Chan . cofmap show -- likewise this demonstrates the Functor instance of OutChan: getStuffOutOf :: OutChan String -> IO [Int] getStuffOutOf = getChanContents . fmap read
All right, leave your love or hate and stay tuned for the new (less stupider) simple-actors lib.
The functor and contravariant functor instances have long since been removed; check out the simple actors package for a simple approach if you want that.
As of v0.4 we implement
Chan from scratch (i.e. not as a simple wrapper
Chan) and in 0.5 we extend that to
STM. The latter chan
type in particular is made much more sensible and understandable by splitting
into read and write sides.