freer-0.2.4.1: Implementation of the Freer Monad

Description

Composable handler for Reader effects. Handy for encapsulating an environment with immutable state for interpreters.

Using http://okmij.org/ftp/Haskell/extensible/Eff1.hs as a starting point.

Synopsis

Documentation

data Reader e v where Source #

Constructors

ask :: Member (Reader e) r => Eff r e Source #

Request a value for the environment

asks :: (b -> a) -> Eff '[Reader b] a Source #

Request a value from the environment and applys as function

runReader :: Eff (Reader e ': r) w -> e -> Eff r w Source #

local :: forall e a r. Member (Reader e) r => (e -> e) -> Eff r a -> Eff r a Source #

Locally rebind the value in the dynamic environment This function is like a relay; it is both an admin for Reader requests, and a requestor of them

In this example the Reader monad provides access to variable bindings. Bindings are a Map of integer variables. The variable count contains number of variables in the bindings. You can see how to run a Reader effect and retrieve data from it with runReader, how to access the Reader data with ask and asks.

import Control.Monad.Freer
import Data.Map as Map
import Data.Maybe

type Bindings = Map String Int

-- Returns True if the "count" variable contains correct bindings size.
isCountCorrect :: Bindings -> Bool
isCountCorrect bindings = run $runReader calc_isCountCorrect bindings -- The Reader effect, which implements this complicated check. calc_isCountCorrect :: Eff '[Reader Bindings] Bool calc_isCountCorrect = do count <- asks (lookupVar "count") bindings <- (ask :: Eff '[Reader Bindings] Bindings) return (count == (Map.size bindings)) -- The selector function to use with 'asks'. -- Returns value of the variable with specified name. lookupVar :: String -> Bindings -> Int lookupVar name bindings = fromJust (Map.lookup name bindings) sampleBindings :: Map.Map String Int sampleBindings = Map.fromList [("count",3), ("1",1), ("b",2)] main = do putStr$ "Count is correct for bindings " ++ (show sampleBindings) ++ ": "
putStrLn $show (isCountCorrect sampleBindings) Example 2: Modifying Reader Content With local Shows how to modify Reader content with local. import Control.Monad.Freer import Control.Monad.Freer.Reader import Data.Map as Map import Data.Maybe type Bindings = Map String Int calculateContentLen :: Eff '[Reader String] Int calculateContentLen = do content <- (ask :: Eff '[Reader String] String) return (length content) -- Calls calculateContentLen after adding a prefix to the Reader content. calculateModifiedContentLen :: Eff '[Reader String] Int calculateModifiedContentLen = local ("Prefix " ++) calculateContentLen main :: IO () main = do let s = "12345"; let modifiedLen = run$ runReader calculateModifiedContentLen s;
let len = run $runReader calculateContentLen s ; putStrLn$ "Modified 's' length: " ++ (show modifiedLen)
putStrLn \$ "Original 's' length: " ++ (show len)