A typeclass abstraction over much of Control.Concurrent (and some extras!). If you're looking for a general introduction to Haskell concurrency, you should check out the excellent Parallel and Concurrent Programming in Haskell, by Simon Marlow. If you are already familiar with concurrent Haskell, just change all the imports from Control.Concurrent. to Control.Concurrent.Classy. and fix the type errors.

A brief list of supported functionality:

  • Threads: the forkIO* and forkOn* functions, although bound threads are not supported.
  • Getting and setting capablities.
  • Yielding and delaying.
  • Mutable state: STM, MVar, and IORef.
  • Atomic compare-and-swap for IORef.
  • Exceptions.
  • All of the data structures in Control.Concurrent. and Control.Concurrent.STM. have typeclass-abstracted equivalents.
  • A reimplementation of the async package, providing a higher-level interface over threads, allowing users to conveniently run MonadConc operations asynchronously and wait for their results.

This is quite a rich set of functionality, although it is not complete. If there is something else you need, file an issue!

This used to be part of dejafu, but with the dejafu- release, it was split out into its own package.

The documentation of the latest developmental version is available online.

Why this and not something else?

  • Why not base: like lifted-base, concurrency uses typeclasses to make function types more generic. This automatically eliminates calls to lift in many cases, resulting in clearer and simpler code.

  • Why not lifted-base: fundamentally, lifted-base is still using actual threads and actual mutable variables. When using a concurrency-specific typeclass, this isn't necessarily the case. The dejafu library provides non-IO-based implementations to allow testing concurrent programs.

  • Why not IOSpec: IOSpec provides many of the operations this library does, however it uses a free monad to do so, which has extra allocation overhead. Furthermore, it does not expose enough of the internals in order to accurately test real-execution semantics, such as relaxed memory.


Bug reports, pull requests, and comments are very welcome!

Feel free to contact me on GitHub, through IRC (#haskell on freenode), or email (


Release Notes

All notable changes to this project will be documented in this file.

This project is versioned according to the Package Versioning Policy, the de facto standard Haskell versioning scheme. [2017-06-07] (tag: concurrency-


  • The isEmptyMVar function is now implemented using tryReadMVar instead of a combination of tryTakeMVar and putMVar. It no longer modifies the contents of the MVar and can no longer block.


  • There is now a changelog. [2017-04-05] (tag: concurrency-


  • New functions:
    • uninterruptibleCancel function, which is cancel inside an uninterruptible mask.
    • replicateConcurrently function, which performs an action many times in separate threads.
    • concurrently_, mapConcurrently_, forConcurrently_, and replicateConcurrently_ functions, which discard the result of the non-_ version.
  • New instances:
    • Semigroup instance for Concurrently when built with base 4.9.
    • Monoid instance for Concurrently.


  • The mask_ and uninterruptibleMask_ functions from Control.Monad.Catch are now re-exported.


  • The cancel and the withAsync functions now block until the Async action terminates, to match changes in the main async package.


  • Every definition, class, and instance now has a Haddock "@since" annotation. [2017-03-04] (git tag: concurrency-


  • The async-dejafu package has been pulled into this package as the Control.Concurrent.Classy.Async module. async-dejafu is now deprecated. [2017-02-21] (git tag: concurrency-


  • The MonadConc class now defines tryReadMVar, a non-blocking version of readMVar akin to tryTakeMVar.
  • The MonadConc class no longer defines _concMessage, there is no alternative provided, it is just gone. [2016-09-10] (git tag: concurrency-

Initial release. Go read the API docs.

comments powered byDisqus