cleff: Fast and concise extensible effects

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain] [Publish]

cleff is an effect system for building modular, well-abstracted and performant programs. It provides:

You can use cleff out of the box, with little to no boilerplate. To get started, use the module Cleff as a starting point.

[Skip to Readme]


Change log
Dependencies atomic-primops (>=0.8 && <0.9), base (>=4.12 && <4.17), containers (>=0.5 && <0.7), exceptions (>=0.10 && <0.11), microlens (>=0.1 && <0.5), monad-control (>=1 && <1.1), primitive (>=0.6.4 && <0.8), stm (>=2.5 && <2.6), template-haskell (>=2.14 && <2.19), th-abstraction (>=0.2 && <0.5), transformers-base (>=0.4 && <0.5), unliftio-core (>=0.1.1 && <0.3) [details]
License BSD-3-Clause
Copyright 2021 Xy Ren
Author Xy Ren
Category Control, Effect, Language
Home page
Bug tracker
Source repo head: git clone
Uploaded by daylily at 2022-06-03T04:03:39Z




Manual Flags


Make IOE a real effect. This is only for reference purposes and should not be enabled in production code.


Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info


Maintainer's Corner

For package maintainers and hackage trustees

Readme for cleff-

[back to package description]

cleff - fast and concise extensible effects

GitHub Workflow Status Hackage

cleff is an extensible effects library for Haskell, with a focus on the balance of performance, expressiveness and ease of use. It provides a set of predefined effects that you can conveniently reuse in your program, as well as low-boilerplate mechanisms for defining and interpreting new domain-specific effects on your own.

In essence, cleff offers:


This is the code that defines the classic Teletype effect. It only takes 20 lines to define the effect and two interpretations, one using stdio and another reading from and writing to a list:

import Cleff
import Cleff.Input
import Cleff.Output
import Cleff.State
import Data.Maybe (fromMaybe)

-- Effect definition
data Teletype :: Effect where
  ReadTTY :: Teletype m String
  WriteTTY :: String -> Teletype m ()
makeEffect ''Teletype

-- Effect Interpretation via IO
runTeletypeIO :: IOE :> es => Eff (Teletype : es) a -> Eff es a
runTeletypeIO = interpretIO \case
  ReadTTY    -> getLine
  WriteTTY s -> putStrLn s

-- Effect interpretation via other pure effects
runTeletypePure :: [String] -> Eff (Teletype : es) w -> Eff es [String]
runTeletypePure tty = fmap (reverse . snd)
  . runState [] . outputToListState
  . runState tty . inputToListState
  . reinterpret2 \case
    ReadTTY -> fromMaybe "" <$> input
    WriteTTY msg -> output msg

-- Using the effect

echo :: Teletype :> es => Eff es ()
echo = do
  x <- readTTY
  if null x then pure ()
    else writeTTY x >> echo

echoPure :: [String] -> [String]
echoPure input = runPure $ runTeletypePure input echo

main :: IO ()
main = runIOE $ runTeletypeIO echo

See example/ for more examples.


These are the results of effectful's microbenchmarks, compiled by GHC 8.10.7. Each diagram shows the average run time of each effect library's implementation of an identical program; lower is better. Each benchmark suite has two flavors - shallow and deep - where the shallow variant only uses necessary effects, and the deep variant adds 10 redundant Reader effects, to simulate more realistic scenarios. Keep in mind that these are very short and synthetic programs, and may or may not tell the accurate performance characteristics of different effect libraries in real use.

Differences from effectful

If you know about effectful, you may notice that cleff and effectful seem to make many similar claims and have a similar underlying implementation. In microbenchmarks, cleff is slightly behind effectful. This may make you confused about the differences between the two libraries. To put it simply, cleff has a more versatile and expressive effect interpretation mechanism, and a lighter weight API. In contrast, effectful gains its performance advantage by providing static dispatch for some internal effects, which means they cannot have multiple interpretations.


These are the useful resources that inspired this library's design and implementation.




Blog posts: