chan: Some extra kit for Chans

[ bsd3, concurrency, library ] [ Propose Tags ]

Please see the README on Github at

[Skip to Readme]


Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


  • No Candidates
Versions [RSS] 0.0.0, 0.0.1, 0.0.2, 0.0.3, 0.0.4,
Dependencies async, base (>=4.11 && <5.0), stm [details]
License BSD-3-Clause
Copyright 2018 Athan Clark
Author Athan Clark
Category Concurrency
Home page
Bug tracker
Source repo head: git clone
Uploaded by athanclark at 2018-12-04T17:24:20Z
Distributions LTSHaskell:, NixOS:, Stackage:
Reverse Dependencies 4 direct, 3 indirect [details]
Downloads 3812 total (18 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2018-12-04 [all 1 reports]

Readme for chan-

[back to package description]


This is just some extra Chan and TChan kit that might help the average user. It relies on spawning threads with async and either canceling (debouncing) or waiting (throttling) messages.

Unfortunately, the current design is slightly untyped in the sense that the channel which you supply is the output channel, and the returned channel is the one you would write to. I'm not sure how this should be fixed. There's a series of "typed" alternatives to each underlying channel type, that allows users to restrict them to "read-only", "write-only", or "Writable a => ..." etc.

An example might be the following:

import Control.Concurrent.Chan (readChan)
import Control.Concurrent.Chan.Scope (Scope (..))
import Control.Concurrent.Chan.Typed (ChanRW)
import Control.Concurrent.Chan.Extra (allowReading, throttleStatic, intersperseStatic)

-- For example, some websockets:

data SomeMessage
  = Ping
  | Foo
  -- | ...

throttleLayer :: ChanRW 'Read SomeMessage -> IO (ChanRW 'Write SomeMessage)
throttleLayer output = do
  (x,_) <- throttleStatic output 1000000 -- nanoseconds, = 1 second
  pure x

pingLayer :: ChanRW 'Read SomeMessage -> IO (ChanRW 'Write SomeMessage)
pingLayer output = do
  (x,_,_) <- intersperseStatic output (pure Ping) 1000000
  pure x

performWebsocket :: ChanRW 'Read SomeMessage -> IO ()
performWebsocket output = do
  sendable <- pingLayer . allowReading =<< throttleLayer output
  emittingThread <- async $ forever $ do
    -- the thread that actually facilitates the sending of messages queued in the chans
    msg <- readChanRW output
    send msg -- something like that - it'll include Ping messages for us,
             -- and throttle the outgoing messages at the same time.
  writeChanRW sendable Foo