Implementation of a friendly effect system for Haskell.

Version on this page:
LTS Haskell 12.22:
Stackage Nightly 2018-12-12:
Latest on Hackage:

See all snapshots freer-simple appears in

BSD3 licensed by Allele Dev, Ixcom Core Team, Alexis King, and other contributors
Maintained by Alexis King

Module documentation for

There are no documented modules for this package.

Freer: Extensible Effects with Freer Monads Build Status


The freer-simple library (a fork of freer-effects) is an implementation of an effect system for Haskell, which is based on the work of Oleg Kiselyov et al.:

Much of the implementation is a repackaging and cleaning up of the reference materials provided here.


The key features of freer-simple are:

  • An efficient effect system for Haskell as a library.
  • Implementations for several common Haskell monads as effects:
    • Reader
    • Writer
    • State
    • Trace
    • Error
  • Core components for defining your own Effects.

Example: Console DSL

Here’s what using freer-simple looks like:

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
module Console where

import Control.Monad.Freer
import Control.Monad.Freer.Error
import Control.Monad.Freer.State
import Control.Monad.Freer.Writer
import System.Exit hiding (ExitCode(ExitSuccess))

                               -- Effect Model --
data Console r where
  PutStrLn    :: String -> Console ()
  GetLine     :: Console String
  ExitSuccess :: Console ()

putStrLn' :: Member Console effs => String -> Eff effs ()
putStrLn' = send . PutStrLn

getLine' :: Member Console effs => Eff effs String
getLine' = send GetLine

exitSuccess' :: Member Console effs => Eff effs ()
exitSuccess' = send ExitSuccess

                          -- Effectful Interpreter --
runConsole :: Eff '[Console, IO] a -> IO a
runConsole = runM . interpretM (\case
  PutStrLn msg -> putStrLn msg
  GetLine -> getLine
  ExitSuccess -> exitSuccess)

                             -- Pure Interpreter --
runConsolePure :: [String] -> Eff '[Console] w -> [String]
runConsolePure inputs req = snd . fst $
    run (runWriter (runState inputs (runError (reinterpret3 go req))))
    go :: Console v -> Eff '[Error (), State [String], Writer [String]] v
    go (PutStrLn msg) = tell [msg]
    go GetLine = get >>= \case
      [] -> error "not enough lines"
      (x:xs) -> put xs >> pure x
    go ExitSuccess = throwError ()


Contributions are welcome! Documentation, examples, code, and feedback - they all help.

Developer Setup

The easiest way to start contributing is to install stack. Stack can install GHC/Haskell for you, and automates common developer tasks.

The key commands are:

  • stack setup — install required version of GHC compiler
  • stack build — builds project, dependencies are automatically resolved
  • stack test — builds project, its tests, and executes the tests
  • stack bench — builds project, its benchmarks, and executes the benchamks
  • stack ghci — start a REPL instance with a project modules loaded
  • stack clean
  • stack haddock — builds documentation

More information about stack can be found in its documentation.


This project is distributed under a BSD3 license. See the included LICENSE file for more details.


The freer-simple package started as a fork of freer-effects by Ixperta Solutions, which in turn is a fork of freer by Allele Dev. All implementations are based on the paper and reference implementation by Oleg Kiselyov. In particular:

There will be deviations from the source.

Changes (November 15th, 2018)

  • Improved makeEffect from Control.Monad.Freer.TH to support more datatypes (#17). (October 23rd, 2018)

  • Added Control.Monad.Freer.TH, which provides a makeEffect function that automatically generates boilerplate operations using send for an effect (#15). (February 20th, 2018)

  • Changed the implementation of LastMember to avoid an issue similar to the one with Member fixed in that could cause the constraint to unnecessarily fail to solve (#6).
  • Changed the order of the type variables in interpretM to be more consistent with other functions (only relevant in combination with TypeApplications).
  • Re-exported (~>) from Control.Natural through Control.Monad.Freer. (January 31st, 2018)

  • Fixed a bug that could cause Member constraints to erroneously fail to solve (#3). (January 27th, 2018)

  • Added subsume to Control.Monad.Freer for deduplicating effects.
  • Added gets to Control.Monad.Freer.State (#1). (December 7th, 2017)

  • Initial release.
comments powered byDisqus