diff --git a/src/Control/Monad/Freer.hs b/src/Control/Monad/Freer.hs index b21d236..f4f0650 100644 --- a/src/Control/Monad/Freer.hs +++ b/src/Control/Monad/Freer.hs @@ -86,7 +86,7 @@ implemented in-memory in terms of 'Control.Monad.Freer.State.State'. With runInMemoryFileSystem :: [('FilePath', 'String')] -> 'Eff' (FileSystem ': effs) '~>' 'Eff' effs runInMemoryFileSystem initVfs = 'Control.Monad.Freer.State.evalState' initVfs '.' fsToState where fsToState :: 'Eff' (FileSystem ': effs) '~>' 'Eff' ('Control.Monad.Freer.State.State' [('FilePath', 'String')] ': effs) - fsToState = 'reinterpret' '$' \case + fsToState = 'reinterpret' '$' \\case ReadFile path -> 'Control.Monad.Freer.State.get' '>>=' \\vfs -> case 'lookup' path vfs of 'Just' contents -> 'pure' contents 'Nothing' -> 'error' ("readFile: no such file " ++ path) diff --git a/src/Control/Monad/Freer/Internal.hs b/src/Control/Monad/Freer/Internal.hs index de96a4c..091ae85 100644 --- a/src/Control/Monad/Freer/Internal.hs +++ b/src/Control/Monad/Freer/Internal.hs @@ -356,9 +356,12 @@ raise = loop -- Nondeterministic Choice -- -------------------------------------------------------------------------------- --- | A data type for representing nondeterminstic choice. +-- | A data type for representing nondeterministic choice. data NonDet a where + -- | Terminates the current branch of the computation. MZero :: NonDet a + -- | Splits the computation into two branches, + -- producing 'True' in one branch and 'False' in the other. MPlus :: NonDet Bool instance Member NonDet effs => Alternative (Eff effs) where diff --git a/src/Control/Monad/Freer/NonDet.hs b/src/Control/Monad/Freer/NonDet.hs index 4b4397d..3ee4f11 100644 --- a/src/Control/Monad/Freer/NonDet.hs +++ b/src/Control/Monad/Freer/NonDet.hs @@ -28,7 +28,7 @@ import Control.Monad.Freer.Internal , tsingleton ) --- | A handler for nondeterminstic effects. +-- | A handler for nondeterministic effects. makeChoiceA :: Alternative f => Eff (NonDet ': effs) a @@ -38,6 +38,8 @@ makeChoiceA = handleRelay (pure . pure) $ \m k -> MZero -> pure empty MPlus -> (<|>) <$> k True <*> k False +-- | Attempt to split the nondeterministic computation into its +-- first result and the remainder of the computation. msplit :: Member NonDet effs => Eff effs a diff --git a/src/Control/Monad/Freer/Reader.hs b/src/Control/Monad/Freer/Reader.hs index 6c661b8..1358df7 100644 --- a/src/Control/Monad/Freer/Reader.hs +++ b/src/Control/Monad/Freer/Reader.hs @@ -41,7 +41,7 @@ data Reader r a where ask :: forall r effs. Member (Reader r) effs => Eff effs r ask = send Ask --- | Request a value of the environment, and apply as selector\/projection +-- | Request a value of the environment, and apply a selector\/projection -- function to it. asks :: forall r effs a @@ -72,66 +72,65 @@ local f m = do -- -- In this example the 'Reader' effect 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'. +-- the number of variables in the bindings. You can see how to run a @Reader@ +-- effect and retrieve data from it with 'runReader', and 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 --- > --- > -- Returns True if the "count" variable contains correct bindings size. --- > isCountCorrect :: Bindings -> Bool --- > isCountCorrect bindings = run $ runReader bindings calc_isCountCorrect --- > --- > -- 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 :: IO () --- > main = putStrLn --- > $ "Count is correct for bindings " ++ show sampleBindings ++ ": " --- > ++ show (isCountCorrect sampleBindings) +-- @ +-- import Control.Monad.Freer +-- import Control.Monad.Freer.Reader +-- import Data.Map (Map, (!)) +-- import qualified Data.Map as Map +-- +-- type Bindings = Map String Int +-- +-- -- Returns whether the "count" variable contains the correct bindings size. +-- isCountCorrect :: Bindings -> Bool +-- isCountCorrect bindings = run $ 'runReader' bindings checkCount +-- +-- -- The Reader effect, which implements this complicated check. +-- checkCount :: 'Eff' \'['Reader' Bindings] Bool +-- checkCount = do +-- count <- 'asks' (lookupVar "count") +-- bindings <- ('ask' :: Eff \'[Reader Bindings] Bindings) +-- return (count == Map.size bindings) +-- +-- -- The selector function to use with 'asks'. +-- -- Returns the value of the variable with specified name. +-- lookupVar :: String -> Bindings -> Int +-- lookupVar name bindings = bindings ! name +-- +-- sampleBindings :: Bindings +-- sampleBindings = Map.fromList [("count", 3), ("1", 1), ("b", 2)] +-- +-- main :: IO () +-- main = putStrLn +-- $ "Count is correct for bindings " ++ show sampleBindings ++ ": " +-- ++ 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 --- > --- > 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 s calculateModifiedContentLen --- > let len = run $ runReader s calculateContentLen --- > putStrLn $ "Modified 's' length: " ++ (show modifiedLen) --- > putStrLn $ "Original 's' length: " ++ (show len) +-- @ +-- import Control.Monad.Freer +-- import Control.Monad.Freer.Reader +-- +-- 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' s calculateModifiedContentLen +-- let len = run $ runReader s calculateContentLen +-- putStrLn $ "Modified \'s\' length: " ++ (show modifiedLen) +-- putStrLn $ "Original \'s\' length: " ++ (show len) +-- @ diff --git a/src/Control/Monad/Freer/State.hs b/src/Control/Monad/Freer/State.hs index deadd1a..d63b699 100644 --- a/src/Control/Monad/Freer/State.hs +++ b/src/Control/Monad/Freer/State.hs @@ -12,7 +12,7 @@ -- Composable handler for 'State' effects. Handy for passing an updatable state -- through a computation. -- --- Some computations may not require the full power of 'State' effect: +-- Some computations may not require the full power of the 'State' effect: -- -- * For a read-only state, see "Control.Monad.Freer.Reader". -- * To accumulate a value without using it on the way, see @@ -57,7 +57,7 @@ get = send Get put :: forall s effs. Member (State s) effs => s -> Eff effs () put s = send (Put s) --- | Modify the current state of type @s :: *@ using provided function +-- | Modify the current state of type @s :: *@ using the provided function -- @(s -> s)@. modify :: forall s effs. Member (State s) effs => (s -> s) -> Eff effs () modify f = fmap f get >>= put diff --git a/src/Control/Monad/Freer/TH.hs b/src/Control/Monad/Freer/TH.hs index df09d66..aaa26a6 100644 --- a/src/Control/Monad/Freer/TH.hs +++ b/src/Control/Monad/Freer/TH.hs @@ -60,7 +60,7 @@ makeEffect = genFreer True -- -- -- | Output a string. -- output :: Member Lang effs --- => String -- ^ String to output. +-- => String -- ^ String to output. -- -> Eff effs () -- ^ No result. -- @ -- diff --git a/src/Control/Monad/Freer/Trace.hs b/src/Control/Monad/Freer/Trace.hs index 9e78edb..cfb884f 100644 --- a/src/Control/Monad/Freer/Trace.hs +++ b/src/Control/Monad/Freer/Trace.hs @@ -8,7 +8,7 @@ -- Portability: GHC specific language extensions. -- -- Composable handler for 'Trace' effects. Trace allows one to debug the --- operation of sequences of effects by outputing to the console. +-- operation of sequences of effects by outputting to the console. -- -- Using as a starting point. module Control.Monad.Freer.Trace diff --git a/src/Control/Monad/Freer/Writer.hs b/src/Control/Monad/Freer/Writer.hs index 45a0012..c156105 100644 --- a/src/Control/Monad/Freer/Writer.hs +++ b/src/Control/Monad/Freer/Writer.hs @@ -10,8 +10,8 @@ -- Portability: GHC specific language extensions. -- -- 'Writer' effects, for writing\/appending values (line count, list of --- messages, etc.) to an output. Current value of 'Writer' effect output is not --- accessible to the computation. +-- messages, etc.) to an output. The current value of the 'Writer' effect output +-- is not accessible to the computation. -- -- Using as a starting point. module Control.Monad.Freer.Writer @@ -28,7 +28,7 @@ import Data.Monoid ((<>)) import Control.Monad.Freer.Internal (Eff, Member, handleRelay, send) --- | Writer effects - send outputs to an effect environment. +-- | Writer effects: send outputs to an effect environment. data Writer w r where Tell :: w -> Writer w ()