diff --git a/src/Control/Monad/Freer/Reader.hs b/src/Control/Monad/Freer/Reader.hs index 73a88f3..cad55bf 100644 --- a/src/Control/Monad/Freer/Reader.hs +++ b/src/Control/Monad/Freer/Reader.hs @@ -26,6 +26,12 @@ module Control.Monad.Freer.Reader ( ask, runReader, local + -- * Example 1: Simple Reader Usage + -- $simpleReaderExample + + -- * Example 2: Modifying Reader Content With @local@ + -- $localExample + ) where import Control.Monad.Freer.Internal @@ -54,3 +60,79 @@ local f m = do let h :: Reader e v -> Arr r v a -> Eff r a h Reader g = g e interpose return h m + + +{- $simpleReaderExample + +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 Control.Monad.Freer.Reader +>import Data.Map as Map +>import Data.Maybe +> +>type Bindings = Map String Int +> +>asks :: (b -> a) -> Eff '[Reader b] a +>asks f = ask >>= return . f +> +>-- 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) +-} + +{- $localExample + +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 +> +> asks :: (b -> a) -> Eff '[Reader b] a +> asks f = ask >>= return . f +> +> 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) +-}