HORIZON HASKELLDocslts/ghc-9.14.x3e2d5682026-10-11Search names, modules, packages, or :: a typeCtrl K

GHC 9.14.1 · lts/ghc-9.14.x · 3e2d568 · 2026-10-11

Moduleextensible-effects-5.0.0.1Haskell2010

Control.Eff.QuickStart

This module contains several tiny examples of how to use effects. For technical details, see the documentation in the effect-modules.

Note that most examples given here are very small. For them, using Eff monad is more complicated compared to a standard functional approach. The power of extensible effects lie in the fact that these computations can be used to construct much more complicated programs by composing the little pieces shown here.

This module imports and reexports modules from this library and requires some language extensions:

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MonoLocalBinds #-}

import Control.Eff
import Control.Eff.Reader.Lazy
import Control.Eff.Writer.Lazy
import Control.Eff.State.Lazy
import Control.Eff.Exception

If you want to see what each extension is good for, you can disable it and see what GHC will complain about.

  • 9 values

Examples

9 declarations
valueoneMore :: Member (Reader Int) r => Eff r Int
#

an effect that returns a number one more than the given

oneMore = do
  x <- ask -- query the environment
  return $ x + 1 -- add one to the asked value and return it
valuepopState :: Member (State [Int]) r => Eff r (Maybe Int)
#

an effectul computation using state. The state is of type [Int]. This function takes the head off the list, if it is there and return it. If state is the empty list, then it stays the same and returns Nothing.

popState = do
 stack <- get
 case stack of
   []       -> return Nothing
   (x : xs) -> do
     put xs
     return $ Just x
valuerunOneMore :: Int -> Int
#

Run the oneMore effectful function by giving it a value to read.

runOneMore i = run . runReader i $ oneMore
Example1 expression
runOneMore 12
valuerunPopState :: [Int] -> (Maybe Int, [Int])
#

run the popState effectful computation based on initial state. The result-type is the result of the computation Maybe Int together with the state at the end of the computation [Int]

runPopState xs = run . runState xs $ popState
Example1 expression
runPopState  [1, 2, 3](Just 1,[2,3])
Example1 expression
runPopState [](Nothing,[])

Run the someting effectful computation given in the previous function. The handlers apply from bottom to top - so this is the reading direction.

runSomething1 initialState newValue =
  run . -- run the Eff-monad with no effects left
  runError . -- run the error part of the effect. This introduces the Either in the result.
  runState initialState . -- handle the state-effect providing an initial state giving back a pair.
  runReader newValue $ -- provide the computation with the dynamic value to read/ask for
  something -- the computation - function
Example1 expression
runSomething1 [] (-0.5)Left (-0.5)
Example1 expression
runSomething1 [2] 1.3Right (3,[1,2])

Run the something effectful computation given above. This has an alternative ordering of the effect-handlers.

The used effect-handlers are the same are used in slightly different order: The runState and runError methods are swapped, which results in a different output type and run-semantics.

runSomething1 initialState newValue =
  run .
  runState initialState .
  runError .
  runReader newValue $
  something -- the computation - function
Example1 expression
runSomething2 [4] (-2.4)(Left (-2.4),[4])
Example1 expression
runSomething2 [4] 5.9(Right 10,[6,4])
valuerunTooBig :: Int -> Either String Int
#

run the tooBig effect based on a provided Int.

runTooBig i = run . runError $ tooBig i
Example1 expression
runTooBig 1Right 1
Example1 expression
runTooBig 200Left "200"
valuesomething :: (Member (Reader Float) r, Member (State [Integer]) r, Member (Exc Float) r) => Eff r Integer
#

An effectful computation with multiple effects:

  • A value gets read

  • an error can be thrown depending on the read value

  • state gets read and transformed

All these effects are composed using the Eff monad using the corresponding Effect types.

something = do
  readValue :: Float <- ask -- read a value from the environment
  when (readValue < 0) $ throwError readValue  -- if the value is negative, throw an error
  modify (l -> (round readValue :: Integer) : l) -- add the rounded read element to the list
  currentState :: [Integer] <- get -- get the state after the modification
  return $ sum currentState -- sum the elements in the list and return that
valuetooBig :: Member (Exc String) r => Int -> Eff r Int
#

an effectful function that can throw an error

tooBig i = do
  when (i > 100) $ throwError $ show i
  return i

Imported effect modules

0 declarations