-module Control.Monad.X.Trans
- ( -- * General transformer classes
- MonadTrans(..),
- HasBaseMonad(..),
-
- -- * Plumbing transformers
- -- $PlumbingDoc
-
- -- ** Reader
- MonadReader(..),
- -- $MonadReaderDoc
- asks,
- localSet,
-
- -- ** Writer
- MonadWriter(..),
- -- $MonadWriterDoc
- listens,
- censor,
- pass,
-
- -- ** State
- MonadState(..),
- -- $MonadStateDoc
- gets,
- modify,
-
- -- * Control transformers
- -- $ControlDoc
-
- -- ** Exceptions
- MonadError(..),
- -- $MonadErrorDoc
-
- -- ** Non-determinism
- MonadNondet(..),
- -- $MonadNondetDoc
-
- -- ** Resumptions
- MonadResume(..),
- -- $MonadResumeDoc
-
- -- ** Continuations
- MonadCont(..),
- -- $MonadContDoc
- )
- where
-
-import Prelude (Monad(..),(.),const,IO,Maybe,id)
-import Control.Monad(MonadPlus,liftM)
-
-import Data.Monoid(Monoid)
-
-
-
---------------------------------------------------------------------------------
--- | Provides a way of going across one transformer layer.
-
-class MonadTrans t where
- lift :: Monad m => m a -> t m a
- -- ^ Provides a way of going across one transformer layer.
-
-
---------------------------------------------------------------------------------
--- | The predicate @HasBaseMonad m n@ indicates that 'm' is a monad
--- built by applying a number of transformers to 'n'.
-
-class (Monad m, Monad n) => HasBaseMonad m n | m -> n where
- inBase :: n a -> m a
- -- ^ Provides a way of going across multiple transformer layers,
- -- all the way to the innermost atomic monad.
-
-
--- Move me somewhere else.
-instance HasBaseMonad IO IO where inBase = id
-instance HasBaseMonad [] [] where inBase = id
-instance HasBaseMonad Maybe Maybe where inBase = id
-
-
-
-
-{- $PlumbingDoc
- /Plumbing transformers/ take care of propagating information around in a computation.
-They all commute with each other. This means that it doesn't meter
-in what order they are added to a computation, the final effect is the same.
--}
-
--- | A reader monad has the ability to propagate around a read-only environment.
--- One can think of the environment as a special read only variable that can
--- be accessed via the methods of the class.
-
-class (Monad m) => MonadReader r m | m -> r where
- ask :: m r
- -- ^ Read the value of the variable.
-
- local :: (r -> r) -> m a -> m a
- -- ^ The method @local f m@ uses @f@ to change the value of the variable
- -- for the duration of a computation @m@. After @m@ completes its execution
- -- the original value of the variable is restored.
-
-{- $MonadReaderDoc
- Read-only variables are useful when some information needs to be carried
-around, but is not used all the time. Such a situation may occur when a deeply nested
-function call needs the information, but most of the functions involved in
-a computation will not use it and simply pass it around. Read-only variables
-are very closely related to /implicit parameters/ <...>.
-See also `MonadWriter'.
--}
-
-
--- | Gets specific component of the environment, using the projection function
--- supplied.
-asks :: (MonadReader r m) => (r -> a) -> m a
-asks f = liftM f ask
-
-
--- | Temporarily sets the value of the read-only variable. One can think of
--- @localSet x m@ as a @let@ construct.
-localSet :: MonadReader r m => r -> m a -> m a
-localSet = local . const
-
-
--- | A writer monad has the ability to collect a number of outputs generated
--- during a computation. It is like carrying around a buffer that can be
--- manipulated with the methods of the class. The 'Monoid' class specifies
--- how to make an empty buffer, and how to join two buffers together.
-class (Monoid w, Monad m) => MonadWriter w m | m -> w where
- tell :: w -> m ()
- -- ^ @tell w@ appends the new information @w@ to the buffer.
-
- listen :: m a -> m (a, w)
- -- ^ @listen m@ moves the contents of the buffer of computation @m@ to its result.
- -- The resulting computation has an empty buffer.
-
-{- $MonadWriterDoc
- Buffer variables are often useful when one needs to collect some
-information, for example while traversing a data structure. In a sense,
-they are the dual of read-only variables, as they propagate outputs
-of functions, rather then their inputs.
--}
-
-
--- | Gets specific component of the output, using the projection function supplied.
-listens :: (MonadWriter w m) => (w -> b) -> m a -> m (a, b)
-listens f m = liftM (\ ~(a,w) -> (a,f w)) (listen m)
-
-
--- | @censor f m@ behaves like @m@ except its output is modified by @f@.
-censor :: MonadWriter w m => (w -> w) -> m a -> m a
-censor f m = do (a,w) <- listen m
- tell (f w) -- the media :-)
- return a
-
--- | NOTE: SHOULD THIS BE IN THE LIBRARY?
--- Does what the type suggests.
-pass :: (MonadWriter w m) => m (a, w -> w) -> m a
-pass m = do ((a,f),w) <- listen m
- tell (f w)
- return a
-
-
-
--- | A state monad carries around a piece of state. It is just like
--- having a read-write variable in an imperative language.
-
-class (Monad m) => MonadState s m | m -> s where
- get :: m s
- -- ^ reads the value of the variable
-
- put :: s -> m ()
- -- ^ @put s@ permanently changes the value of the variable to @s@.
-
--- $MonadStateDoc
---
-
--- | Gets specific component of the state, using the projection function supplied.
-gets :: (MonadState s m) => (s -> a) -> m a
-gets f = liftM f get
-
--- | Update the state with a function.
-modify :: (MonadState s m) => (s -> s) -> m ()
-modify f = get >>= put . f
-
-
--- $ControlDoc
--- /Control transformers/ are used to manipulate the control flow in a program.
--- In general they do not commute between themselves and with other transformers.
--- This means that it is important in what order they are added on top of a monad.
--- Different orders yield monads with different behavior. See "FeatureInteract.hs".
-
-
-
--- | An error (or exception) monad is aware that computations may fail.
--- The type @e@ specifies what errors may occur in a computation.
-class (Monad m) => MonadError e m | m -> e where
- throwError :: e -> m a
- -- ^ The method @throwError e@ raises exception @e@.
- -- It never returns a value.
-
- catchError :: m a -> (e -> m a) -> m a
- -- ^ The method @catchError m h@ uses the handler @h@ to handle exceptions
- -- raised in computation @m@. If no exceptions are
- -- raised, the final computation behaves as @m@. It is possible
- -- for the handler itself to throw an exception.
-
--- $ErrorDoc
-
--- | A nondeterminism (or backtracking) monad supports computations that
--- may fail and backtrack or produce multiple results.
---
--- Currently some of the methods in this class are inherited from
--- the class 'MonadPlus' defined in module "Control.Monad".
--- 'mzero' is used to indicate no results.
--- 'mplus' is used to indicate alternatives.
---
--- Since the use of 'MonadPlus' is somewhat overloaded in Haskell
--- (it is also used for exception handling)
--- in the future 'mzero' and 'mplus' may be added explicitly to this class
--- (with different names).
-class (MonadPlus m) => MonadNondet m where
- findAll :: m a -> m [a]
- -- ^ @findAll m@ is analogous to the construct found in logic languages
- -- (e.g. Prolog, Curry). It produces all possible results of @m@.
- commit :: m a -> m a
- -- ^ @commit m@ behaves like @m@ except it will produce at most one result.
- -- Thus, it resembles the /cut/ operator of Prolog.
- -- (VERIFY) @findAll (commit m)@ should never produce a list with more than one element.
-
-class Monad m => MonadResume m where
- delay :: m a -> m a
- force :: m a -> m a
-
--- | TODO.
-class (Monad m) => MonadCont m where
- callCC :: ((a -> m b) -> m a) -> m a
-
-
-
-
-
-