mtl 2.2 → 2.3.2
raw patch · 29 files changed
Files
- CHANGELOG.markdown +64/−2
- Control/Monad/Accum.hs +328/−0
- Control/Monad/Cont.hs +39/−18
- Control/Monad/Cont/Class.hs +111/−25
- Control/Monad/Error.hs +0/−149
- Control/Monad/Error/Class.hs +167/−36
- Control/Monad/Except.hs +153/−0
- Control/Monad/Identity.hs +4/−6
- Control/Monad/List.hs +0/−25
- Control/Monad/RWS.hs +2/−0
- Control/Monad/RWS/CPS.hs +50/−0
- Control/Monad/RWS/Class.hs +19/−11
- Control/Monad/RWS/Lazy.hs +4/−9
- Control/Monad/RWS/Strict.hs +5/−10
- Control/Monad/Reader.hs +28/−20
- Control/Monad/Reader/Class.hs +67/−27
- Control/Monad/Select.hs +316/−0
- Control/Monad/State.hs +1/−0
- Control/Monad/State/Class.hs +63/−26
- Control/Monad/State/Lazy.hs +11/−14
- Control/Monad/State/Strict.hs +10/−13
- Control/Monad/Trans.hs +1/−0
- Control/Monad/Writer.hs +2/−0
- Control/Monad/Writer/CPS.hs +47/−0
- Control/Monad/Writer/Class.hs +70/−24
- Control/Monad/Writer/Lazy.hs +8/−14
- Control/Monad/Writer/Strict.hs +5/−12
- README.markdown +164/−0
- mtl.cabal +41/−26
CHANGELOG.markdown view
@@ -1,10 +1,72 @@-2.2+2.3.2 -- 2025-12-07+-----+* Add `Accum` monad.+* Generalize `MonadAccum` instance for all `Monad m` underlying `AccumT`, not just `Identity`.+* Allow building monokinded `ContT` if the compiler is MicroHs.+* Fix an issue where `QuantifiedConstraints` in the definition of `liftCallCC` was was preventing building under certain conditions.+* Add `Control.Monad.Class.onError`.+* Add various instances for `Data.Functor.Product.Product`.++2.3.1 -- 2022-09-10+-----+* Add `modifyError` to `Control.Monad.Error.Class`, and re-export from+ `Control.Monad.Except`.+* Make the `MonadCont` instance for `ContT` more polykinded; now, `r` is allowed+ to be of an arbitrary kind `k`, rather than only `Type`.+* Add a generic `liftCallCC` for use with any `MonadTrans`.+* Add `modifyError` to `Control.Monad.Error.Class`+* Return re-export of `ExceptT` and related functions to `Control.Monad.Except`.+* Add `label` function to `MonadCont`++2.3 -- 2022-05-07 ---+* Add instances for `Control.Monad.Trans.Writer.CPS` and+ `Control.Monad.Trans.RWS.CPS` from `transformers` 0.5.6 and add+ `Control.Monad.Writer.CPS` and `Control.Monad.RWS.CPS`.+* `Control.Monad.Cont` now re-exports `evalCont` and `evalContT`.+* Add `tryError`, `withError`, `handleError`, and `mapError` to+ `Control.Monad.Error.Class`, and re-export from `Control.Monad.Except`.+* Remove `Control.Monad.List` and `Control.Monad.Error`.+* Remove instances of deprecated `ListT` and `ErrorT`.+* Remove re-exports of `Error`.+* Add instances for `Control.Monad.Trans.Accum` and+ `Control.Monad.Trans.Select`.+* Require GHC 8.6 or higher, and `cabal-install` 3.0 or higher.+* Require `transformers-0.5.6` or higher.+* Add `Control.Monad.Accum` for the `MonadAccum` type class, as well as the+ `LiftingAccum` deriving helper.+* Add `Control.Monad.Select` for the `MonadSelect` type class, as well as the+ `LiftingSelect` deriving helper.+* Remove re-exports of `Control.Monad`, `Control.Monad.Fix` and `Data.Monoid` modules++2.2.2 -- 2018-02-24+-----+* `Control.Monad.Identity` now re-exports `Control.Monad.Trans.Identity`+* Fix a bug in which `Control.Monad.State.Class.modify'` was not as strict in+ the new state as its counterparts in `transformers`+* Add a `MonadError () Maybe` instance+* Add `liftEither :: MonadError e m => Either e a -> m a` to+ `Control.Monad.Except{.Class}`+* Add a `MonadWriter w ((,) w)` instance (when built against `base-4.9` or later)++2.2.1 -- 2014-06-02+-------+* Provide MINIMAL pragmas for `MonadState`, `MonadWriter`, `MonadReader`+* Added a cyclic definition of `ask` in terms of `reader` for consistency with `get`/`put` vs. `state` and `tell` vs. `writer`+* Fix deprecation warnings caused by `transformers` 0.4 deprecating `ErrorT`.+* Added `Control.Monad.Except` in the style of the other `mtl` re-export modules++2.2.0.1 -- 2014-05-05+-------+* Fixed a bug caused by the change in how `transformers` 0.4 exports its data types. We will now export `runFooT` for each transformer again!++2.2 -- 2014-05-05+--- * `transformers` 0.4 support * Added instances for `ExceptT` * Added `modify'` to `Control.Monad.State.*` -2.1.3.1+2.1.3.1 -- 2014-03-24 ------- * Avoid importing `Control.Monad.Instances` on GHC 7.8 to build without deprecation warnings.
+ Control/Monad/Accum.hs view
@@ -0,0 +1,328 @@+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE UndecidableInstances #-}+-- Later GHCs infer DerivingVia as not Safe+-- We just downgrade to Trustworthy and go fish+{-# OPTIONS_GHC -Wno-trustworthy-safe #-}++-- | Module: Control.Monad.Accum+-- Copyright: (C) Koz Ross 2022, Manuel Bärenz 2021+-- License: BSD-3-Clause (see the LICENSE file)+-- Maintainer: koz.ross@retro-freedom.nz+-- Stability: Experimental+-- Portability: GHC only+--+-- [Computation type:] Accumulation (either append-only state, or writer with+-- the ability to read all previous input).+--+-- [Binding strategy:] Binding a function to a monadic value monoidally+-- accumulates the subcomputations (that is, using '<>').+--+-- [Useful for:] Logging, patch-style tracking.+--+-- [Zero and plus:] None.+--+-- [Example type:] @'Control.Monad.Trans.Accum.Accum' w a@+--+-- = A note on commutativity+--+-- Some effects are /commutative/: it doesn't matter which you resolve first, as+-- all possible orderings of commutative effects are isomorphic. Consider, for+-- example, the reader and state effects, as exemplified by 'ReaderT' and+-- 'StrictState.StateT' respectively. If we have+-- @'ReaderT' r ('StrictState.State' s) a@, this is+-- effectively @r -> 'StrictState.State' s a ~ r -> s -> (a, s)@; if we instead have+-- @'StrictState.StateT' s ('Control.Monad.Trans.Reader.Reader' r) a@, this is effectively+-- @s -> 'Control.Monad.Trans.Reader' r (a, s) ~ s -> r -> (a, s)@. Since we+-- can always reorder function arguments (for example, using 'flip', as in+-- this case) without changing the result, these are+-- isomorphic, showing that reader and state are /commutative/, or, more+-- precisely, /commute with each other/.+--+-- However, this isn't generally the case. Consider instead the error and state+-- effects, as exemplified by 'MaybeT' and 'StrictState.StateT' respectively.+-- If we have @'MaybeT' ('Control.Monad.Trans.State.Strict.State' s) a@, this+-- is effectively @'State' s ('Maybe' a) ~ s -> ('Maybe' a, s)@: put simply,+-- the error can occur only in the /result/, but+-- not the state, which always \'survives\'. On the other hand, if we have+-- @'StrictState.StateT' s 'Maybe' a@, this is instead @s -> 'Maybe' (a, s)@: here,+-- if we error, we lose /both/ the state and the result! Thus, error and state effects+-- do /not/ commute with each other.+--+-- As the MTL is capability-based, we support any ordering of non-commutative+-- effects on an equal footing. Indeed, if you wish to use+-- 'Control.Monad.State.Class.MonadState', for+-- example, whether your final monadic stack ends up being @'MaybeT'+-- ('Control.Monad.Trans.State.Strict.State' s)+-- a@, @'StrictState.StateT' s 'Maybe' a@, or anything else, you will be able to write your+-- desired code without having to consider such differences. However, the way we+-- /implement/ these capabilities for any given transformer (or rather, any+-- given transformed stack) /is/ affected by this ordering unless the effects in+-- question are commutative.+--+-- We note in this module which effects the accumulation effect does and doesn't+-- commute with; we also note on implementations with non-commutative+-- transformers what the outcome will be. Note that, depending on how the+-- \'inner monad\' is structured, this may be more complex than we note: we+-- describe only what impact the \'outer effect\' has, not what else might be in+-- the stack.+--+-- = Commutativity of accumulation+--+-- The accumulation effect commutes with the identity effect ('IdentityT'),+-- reader, writer or state effects ('ReaderT', 'StrictWriter.WriterT', 'StrictState.StateT' and any+-- combination, including 'StrictRWS.RWST' for example) and with itself. It does /not/+-- commute with anything else.+module Control.Monad.Accum+ ( -- * Type class+ MonadAccum (..),++ -- * The 'Accum' monad+ Accum.Accum,+ Accum.runAccum,+ Accum.execAccum,+ Accum.evalAccum,+ Accum.mapAccum,++ -- * The 'AccumT' monad transformer+ Accum.AccumT (..),+ Accum.execAccumT,+ Accum.evalAccumT,+ Accum.mapAccumT,+ Accum.readerToAccumT,+ Accum.writerToAccumT,+ Accum.accumToStateT,++ -- * Lifting helper type+ LiftingAccum (..),++ -- * Other functions+ looks,+ )+where++import Control.Monad.Trans.Accum (AccumT)+import qualified Control.Monad.Trans.Accum as Accum+import Control.Monad.Trans.Class (MonadTrans (lift))+import Control.Monad.Trans.Cont (ContT)+import Control.Monad.Trans.Except (ExceptT)+import Control.Monad.Trans.Identity (IdentityT)+import Control.Monad.Trans.Maybe (MaybeT)+import qualified Control.Monad.Trans.RWS.CPS as CPSRWS+import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS+import qualified Control.Monad.Trans.RWS.Strict as StrictRWS+import Control.Monad.Trans.Reader (ReaderT)+import Control.Monad.Trans.Select (SelectT)+import qualified Control.Monad.Trans.State.Lazy as LazyState+import qualified Control.Monad.Trans.State.Strict as StrictState+import qualified Control.Monad.Trans.Writer.CPS as CPSWriter+import qualified Control.Monad.Trans.Writer.Lazy as LazyWriter+import qualified Control.Monad.Trans.Writer.Strict as StrictWriter+import Data.Functor (($>))+import Data.Kind (Type)++-- | The capability to accumulate. This can be seen in one of two ways:+--+-- * A 'Control.Monad.State.Class.MonadState' which can only append (using '<>'); or+-- * A 'Control.Monad.Writer.Class.MonadWriter' (limited to+-- 'Control.Monad.Writer.Class.tell') with the ability to view the result of all previous+-- 'Control.Monad.Writer.Class.tell's.+--+-- = Laws+--+-- 'accum' should obey the following:+--+-- 1. @'accum' ('const' (x, 'mempty'))@ @=@ @'pure' x@+-- 2. @'accum' f '*>' 'accum' g@ @=@+-- @'accum' '$' \\acc -> let (_, v) = f acc+-- (res, w) = g (acc '<>' v) in (res, v '<>' w)@+--+-- If you choose to define 'look' and 'add' instead, their definitions must obey+-- the following:+--+-- 1. @'look' '*>' 'look'@ @=@ @'look'@+-- 2. @'add' 'mempty'@ @=@ @'pure' ()@+-- 3. @'add' x '*>' 'add' y@ @=@ @'add' (x '<>' y)@+-- 4. @'add' x '*>' 'look'@ @=@ @'look' '>>=' \\w -> 'add' x '$>' w '<>' x@+--+-- If you want to define both, the relationship between them is as follows.+-- These are also the default definitions.+--+-- 1. @'look'@ @=@ @'accum' '$' \\acc -> (acc, mempty)@+-- 2. @'add' x@ @=@ @'accum' '$' \\acc -> ('()', x)@+-- 3. @'accum' f@ @=@ @'look' >>= \\acc -> let (res, v) = f acc in 'add' v '$>' res@+--+-- @since 2.3+class (Monoid w, Monad m) => MonadAccum w m | m -> w where+ -- | Retrieve the accumulated result so far.+ look :: m w+ look = accum (,mempty)++ -- | Append a value to the result.+ add :: w -> m ()+ add x = accum $ const ((), x)++ -- | Embed a simple accumulation action into the monad.+ accum :: (w -> (a, w)) -> m a+ accum f = look >>= \acc -> let (res, v) = f acc in add v $> res++ {-# MINIMAL accum | look, add #-}++-- | @since 2.3+instance (Monoid w, Monad m) => MonadAccum w (AccumT w m) where+ look = Accum.look+ add = Accum.add+ accum = Accum.accum++-- | The accumulated value \'survives\' an error: even if the+-- computation fails to deliver a result, we still have an accumulated value.+--+-- @since 2.3+deriving via+ (LiftingAccum MaybeT m)+ instance+ (MonadAccum w m) =>+ MonadAccum w (MaybeT m)++-- | The continuation can see, and interact with, the accumulated value.+--+-- @since 2.3+deriving via+ (LiftingAccum (ContT r) m)+ instance+ (MonadAccum w m) =>+ MonadAccum w (ContT r m)++-- | The accumulated value \'survives\' an exception: even if the computation+-- fails to deliver a result, we still have an accumulated value.+--+-- @since 2.3+deriving via+ (LiftingAccum (ExceptT e) m)+ instance+ (MonadAccum w m) =>+ MonadAccum w (ExceptT e m)++-- | @since 2.3+deriving via+ (LiftingAccum IdentityT m)+ instance+ (MonadAccum w m) =>+ MonadAccum w (IdentityT m)++-- | @since 2.3+deriving via+ (LiftingAccum (CPSRWS.RWST r w s) m)+ instance+ (MonadAccum w' m) =>+ MonadAccum w' (CPSRWS.RWST r w s m)++-- | @since 2.3+deriving via+ (LiftingAccum (LazyRWS.RWST r w s) m)+ instance+ (MonadAccum w' m, Monoid w) =>+ MonadAccum w' (LazyRWS.RWST r w s m)++-- | @since 2.3+deriving via+ (LiftingAccum (StrictRWS.RWST r w s) m)+ instance+ (MonadAccum w' m, Monoid w) =>+ MonadAccum w' (StrictRWS.RWST r w s m)++-- | @since 2.3+deriving via+ (LiftingAccum (ReaderT r) m)+ instance+ (MonadAccum w m) =>+ MonadAccum w (ReaderT r m)++-- | The \'ranking\' function gains the ability to accumulate @w@s each time it+-- is called. The final result will include the entire log of all such calls.+--+-- @since 2.3+deriving via+ (LiftingAccum (SelectT r) m)+ instance+ (MonadAccum w m) =>+ MonadAccum w (SelectT r m)++-- | @since 2.3+deriving via+ (LiftingAccum (LazyState.StateT s) m)+ instance+ (MonadAccum w m) =>+ MonadAccum w (LazyState.StateT s m)++-- | @since 2.3+deriving via+ (LiftingAccum (StrictState.StateT s) m)+ instance+ (MonadAccum w m) =>+ MonadAccum w (StrictState.StateT s m)++-- | @since 2.3+deriving via+ (LiftingAccum (CPSWriter.WriterT w) m)+ instance+ (MonadAccum w' m) =>+ MonadAccum w' (CPSWriter.WriterT w m)++-- | @since 2.3+deriving via+ (LiftingAccum (LazyWriter.WriterT w) m)+ instance+ (MonadAccum w' m, Monoid w) =>+ MonadAccum w' (LazyWriter.WriterT w m)++-- | @since 2.3+deriving via+ (LiftingAccum (StrictWriter.WriterT w) m)+ instance+ (MonadAccum w' m, Monoid w) =>+ MonadAccum w' (StrictWriter.WriterT w m)++-- | A helper type to decrease boilerplate when defining new transformer+-- instances of 'MonadAccum'.+--+-- Most of the instances in this module are derived using this method; for+-- example, our instance of 'ExceptT' is derived as follows:+--+-- > deriving via (LiftingAccum (ExceptT e) m) instance (MonadAccum w m) =>+-- > MonadAccum w (ExceptT e m)+--+-- @since 2.3+newtype LiftingAccum (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) (a :: Type)+ = LiftingAccum (t m a)+ deriving+ ( -- | @since 2.3+ Functor,+ -- | @since 2.3+ Applicative,+ -- | @since 2.3+ Monad+ )+ via (t m)++-- | @since 2.3+instance (MonadTrans t, Monad (t m), MonadAccum w m) => MonadAccum w (LiftingAccum t m) where+ look = LiftingAccum . lift $ look+ add x = LiftingAccum . lift $ add x+ accum f = LiftingAccum . lift $ accum f++-- | Retrieve a function of the accumulated value.+--+-- @since 2.3+looks ::+ forall (a :: Type) (m :: Type -> Type) (w :: Type).+ (MonadAccum w m) =>+ (w -> a) ->+ m a+looks f = f <$> look
Control/Monad/Cont.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE Safe #-}+ {- | Module : Control.Monad.Cont Copyright : (c) The University of Glasgow 2001,@@ -50,35 +52,38 @@ module Control.Monad.Cont ( -- * MonadCont class- MonadCont(..),+ MonadCont.MonadCont(..),+ MonadCont.label,+ MonadCont.label_,+ -- * The Cont monad- Cont,- cont,- runCont,- mapCont,- withCont,+ Cont.Cont,+ Cont.cont,+ Cont.runCont,+ Cont.evalCont,+ Cont.mapCont,+ Cont.withCont, -- * The ContT monad transformer- ContT(..),- mapContT,- withContT,- module Control.Monad,- module Control.Monad.Trans,+ Cont.ContT(ContT),+ Cont.runContT,+ Cont.evalContT,+ Cont.mapContT,+ Cont.withContT, -- * Example 1: Simple Continuation Usage -- $simpleContExample -- * Example 2: Using @callCC@ -- $callCCExample- + -- * Example 3: Using @ContT@ Monad Transformer -- $ContTExample- ) where -import Control.Monad.Cont.Class--import Control.Monad.Trans-import Control.Monad.Trans.Cont+ -- * Example 4: Using @label@+ -- $labelExample+ ) where -import Control.Monad+import qualified Control.Monad.Cont.Class as MonadCont+import qualified Control.Monad.Trans.Cont as Cont {- $simpleContExample Calculating length of a list continuation-style:@@ -165,4 +170,20 @@ @askString@ takes as a parameter a continuation taking a string parameter, and returning @IO ()@. Compare its signature to 'runContT' definition.+-}++{-$labelExample++The early exit behavior of 'Control.Monad.Cont.Class.callCC' can be leveraged to produce other idioms:++> whatsYourNameLabel :: IO ()+> whatsYourNameLabel = evalContT $ do+> (beginning, attempts) <- label (0 :: Int)+> liftIO $ putStrLn $ "Attempt #" <> show attempts+> liftIO $ putStrLn $ "What's your name?"+> name <- liftIO getLine+> when (null name) $ beginning (attempts + 1)+> liftIO $ putStrLn $ "Welcome, " ++ name ++ "!"++Calling @beggining@ will interrupt execution of the block, skipping the welcome message, which will be printed only once at the very end of the loop. -}
Control/Monad/Cont/Class.hs view
@@ -1,3 +1,13 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE QuantifiedConstraints #-}+-- Needed because the CPSed versions of Writer and State are secretly State+-- wrappers, which don't force such constraints, even though they should legally+-- be there.+{-# OPTIONS_GHC -Wno-redundant-constraints #-}+ {- | Module : Control.Monad.Cont.Class Copyright : (c) The University of Glasgow 2001,@@ -50,35 +60,46 @@ module Control.Monad.Cont.Class ( MonadCont(..),+ label,+ label_,+ liftCallCC, ) where +import Data.Kind (Type)+import Control.Monad.Fix (fix) import Control.Monad.Trans.Cont (ContT) import qualified Control.Monad.Trans.Cont as ContT-import Control.Monad.Trans.Error as Error-import Control.Monad.Trans.Except as Except-import Control.Monad.Trans.Identity as Identity-import Control.Monad.Trans.List as List-import Control.Monad.Trans.Maybe as Maybe-import Control.Monad.Trans.Reader as Reader-import Control.Monad.Trans.RWS.Lazy as LazyRWS-import Control.Monad.Trans.RWS.Strict as StrictRWS-import Control.Monad.Trans.State.Lazy as LazyState-import Control.Monad.Trans.State.Strict as StrictState-import Control.Monad.Trans.Writer.Lazy as LazyWriter-import Control.Monad.Trans.Writer.Strict as StrictWriter--import Control.Monad-import Data.Monoid+import Control.Monad.Trans.Except (ExceptT)+import qualified Control.Monad.Trans.Except as Except+import Control.Monad.Trans.Identity (IdentityT)+import qualified Control.Monad.Trans.Identity as Identity+import Control.Monad.Trans.Maybe (MaybeT)+import qualified Control.Monad.Trans.Maybe as Maybe+import Control.Monad.Trans.Reader (ReaderT)+import qualified Control.Monad.Trans.Reader as Reader+import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS+import qualified Control.Monad.Trans.RWS.Strict as StrictRWS+import qualified Control.Monad.Trans.State.Lazy as LazyState+import qualified Control.Monad.Trans.State.Strict as StrictState+import qualified Control.Monad.Trans.Writer.Lazy as LazyWriter+import qualified Control.Monad.Trans.Writer.Strict as StrictWriter+import Control.Monad.Trans.Accum (AccumT)+import qualified Control.Monad.Trans.Accum as Accum+import qualified Control.Monad.Trans.RWS.CPS as CPSRWS+import qualified Control.Monad.Trans.Writer.CPS as CPSWriter+import Control.Monad.Trans.Class (MonadTrans (lift))+import Control.Monad.Signatures (CallCC)+import Control.Monad (join) -class Monad m => MonadCont m where+class Monad m => MonadCont (m :: Type -> Type) where {- | @callCC@ (call-with-current-continuation) calls a function with the current continuation as its argument. Provides an escape continuation mechanism for use with Continuation monads. Escape continuations allow to abort the current computation and return a value immediately.- They achieve a similar effect to 'Control.Monad.Error.throwError'- and 'Control.Monad.Error.catchError'- within an 'Control.Monad.Error.Error' monad.+ They achieve a similar effect to 'Control.Monad.Error.Class.throwError'+ and 'Control.Monad.Error.Class.catchError'+ within an 'Control.Monad.Except.Except' monad. Advantage of this function over calling @return@ is that it makes the continuation explicit, allowing more flexibility and better control@@ -90,25 +111,27 @@ even if it is many layers deep within nested computations. -} callCC :: ((a -> m b) -> m a) -> m a+ {-# MINIMAL callCC #-} +-- | @since 2.3.1+#ifdef __MHS__+-- The ContT type is not polykinded with mhs. instance MonadCont (ContT r m) where+#else+instance forall k (r :: k) (m :: (k -> Type)) . MonadCont (ContT r m) where+#endif callCC = ContT.callCC -- --------------------------------------------------------------------------- -- Instances for other mtl transformers -instance (Error e, MonadCont m) => MonadCont (ErrorT e m) where- callCC = Error.liftCallCC callCC-+-- | @since 2.2 instance MonadCont m => MonadCont (ExceptT e m) where callCC = Except.liftCallCC callCC instance MonadCont m => MonadCont (IdentityT m) where callCC = Identity.liftCallCC callCC -instance MonadCont m => MonadCont (ListT m) where- callCC = List.liftCallCC callCC- instance MonadCont m => MonadCont (MaybeT m) where callCC = Maybe.liftCallCC callCC @@ -132,3 +155,66 @@ instance (Monoid w, MonadCont m) => MonadCont (StrictWriter.WriterT w m) where callCC = StrictWriter.liftCallCC callCC++-- | @since 2.3+instance (Monoid w, MonadCont m) => MonadCont (CPSRWS.RWST r w s m) where+ callCC = CPSRWS.liftCallCC' callCC++-- | @since 2.3+instance (Monoid w, MonadCont m) => MonadCont (CPSWriter.WriterT w m) where+ callCC = CPSWriter.liftCallCC callCC++-- | @since 2.3+instance+ ( Monoid w+ , MonadCont m+ ) => MonadCont (AccumT w m) where+ callCC = Accum.liftCallCC callCC++-- | Introduces a recursive binding to the continuation.+-- Due to the use of @callCC@, calling the continuation will interrupt execution+-- of the current block creating an effect similar to goto/setjmp in C.+--+-- @since 2.3.1+--+label :: MonadCont m => a -> m (a -> m b, a)+label a = callCC $ \k -> let go b = k (go, b) in return (go, a)++-- | Simplified version of `label` without arguments.+-- +-- @since 2.3.1+--+label_ :: MonadCont m => m (m a)+label_ = callCC $ return . fix++-- | Lift a 'ContT.callCC'-style function through any 'MonadTrans'. +--+-- = Note+--+-- For any function @f@, @'liftCallCC' f@ satisfies the [uniformity+-- condition](https://hackage.haskell.org/package/transformers-0.5.6.2/docs/Control-Monad-Signatures.html#t:CallCC)+-- provided that @f@ is quasi-algebraic. More specifically, for any @g@, we must have:+--+-- @+-- 'join' '$' f (\\exit -> 'pure' '$' g (exit '.' 'pure') = f g+-- @+--+-- 'ContT.callCC' is quasi-algebraic; furthermore, for any quasi-algebraic @f@,+-- @'liftCallCC' f@ is also quasi-algebraic. +--+-- = See also+--+-- * [Proof of quasi-algebraic+-- properties](https://gist.github.com/KingoftheHomeless/5927257cc7f6f8a2da685a2045dac204)+-- * [Original issue](https://github.com/haskell/mtl/issues/77)+--+-- @since 2.3.1+liftCallCC :: + forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) (a :: Type) (b :: Type) . + (MonadTrans t, Monad m+#if !MIN_VERSION_transformers(0,6,0) || defined(__MHS__)+ , forall (m' :: Type -> Type) . Monad m' => Monad (t m')+#endif+ ) =>+ CallCC m (t m a) b -> CallCC (t m) a b+liftCallCC f g = join . lift . f $ \exit -> pure $ g (lift . exit . pure)
− Control/Monad/Error.hs
@@ -1,149 +0,0 @@-{-# LANGUAGE CPP #-}-{- |-Module : Control.Monad.Error-Copyright : (c) Michael Weber <michael.weber@post.rwth-aachen.de> 2001,- (c) Jeff Newbern 2003-2006,- (c) Andriy Palamarchuk 2006-License : BSD-style (see the file LICENSE)--Maintainer : libraries@haskell.org-Stability : experimental-Portability : non-portable (multi-parameter type classes)--[Computation type:] Computations which may fail or throw exceptions.--[Binding strategy:] Failure records information about the cause\/location-of the failure. Failure values bypass the bound function,-other values are used as inputs to the bound function.--[Useful for:] Building computations from sequences of functions that may fail-or using exception handling to structure error handling.--[Zero and plus:] Zero is represented by an empty error and the plus operation-executes its second argument if the first fails.--[Example type:] @'Data.Either' String a@--The Error monad (also called the Exception monad).--}--{-- Rendered by Michael Weber <mailto:michael.weber@post.rwth-aachen.de>,- inspired by the Haskell Monad Template Library from- Andy Gill (<http://web.cecs.pdx.edu/~andy/>)--}-module Control.Monad.Error (- -- * Monads with error handling- MonadError(..),- Error(..),- -- * The ErrorT monad transformer- ErrorT(..),- mapErrorT,- module Control.Monad,- module Control.Monad.Fix,- module Control.Monad.Trans,- -- * Example 1: Custom Error Data Type- -- $customErrorExample-- -- * Example 2: Using ErrorT Monad Transformer- -- $ErrorTExample- ) where--import Control.Monad.Error.Class-import Control.Monad.Trans-import Control.Monad.Trans.Error (ErrorT(..), mapErrorT)--import Control.Monad-import Control.Monad.Fix--#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < 707-import Control.Monad.Instances ()-#endif--{- $customErrorExample-Here is an example that demonstrates the use of a custom 'Error' data type with-the 'throwError' and 'catchError' exception mechanism from 'MonadError'.-The example throws an exception if the user enters an empty string-or a string longer than 5 characters. Otherwise it prints length of the string.-->-- This is the type to represent length calculation error.->data LengthError = EmptyString -- Entered string was empty.-> | StringTooLong Int -- A string is longer than 5 characters.-> -- Records a length of the string.-> | OtherError String -- Other error, stores the problem description.->->-- We make LengthError an instance of the Error class->-- to be able to throw it as an exception.->instance Error LengthError where-> noMsg = OtherError "A String Error!"-> strMsg s = OtherError s->->-- Converts LengthError to a readable message.->instance Show LengthError where-> show EmptyString = "The string was empty!"-> show (StringTooLong len) =-> "The length of the string (" ++ (show len) ++ ") is bigger than 5!"-> show (OtherError msg) = msg->->-- For our monad type constructor, we use Either LengthError->-- which represents failure using Left LengthError->-- or a successful result of type a using Right a.->type LengthMonad = Either LengthError->->main = do-> putStrLn "Please enter a string:"-> s <- getLine-> reportResult (calculateLength s)->->-- Wraps length calculation to catch the errors.->-- Returns either length of the string or an error.->calculateLength :: String -> LengthMonad Int->calculateLength s = (calculateLengthOrFail s) `catchError` Left->->-- Attempts to calculate length and throws an error if the provided string is->-- empty or longer than 5 characters.->-- The processing is done in Either monad.->calculateLengthOrFail :: String -> LengthMonad Int->calculateLengthOrFail [] = throwError EmptyString->calculateLengthOrFail s | len > 5 = throwError (StringTooLong len)-> | otherwise = return len-> where len = length s->->-- Prints result of the string length calculation.->reportResult :: LengthMonad Int -> IO ()->reportResult (Right len) = putStrLn ("The length of the string is " ++ (show len))->reportResult (Left e) = putStrLn ("Length calculation failed with error: " ++ (show e))--}--{- $ErrorTExample-@'ErrorT'@ monad transformer can be used to add error handling to another monad.-Here is an example how to combine it with an @IO@ monad:-->import Control.Monad.Error->->-- An IO monad which can return String failure.->-- It is convenient to define the monad type of the combined monad,->-- especially if we combine more monad transformers.->type LengthMonad = ErrorT String IO->->main = do-> -- runErrorT removes the ErrorT wrapper-> r <- runErrorT calculateLength-> reportResult r->->-- Asks user for a non-empty string and returns its length.->-- Throws an error if user enters an empty string.->calculateLength :: LengthMonad Int->calculateLength = do-> -- all the IO operations have to be lifted to the IO monad in the monad stack-> liftIO $ putStrLn "Please enter a non-empty string: "-> s <- liftIO getLine-> if null s-> then throwError "The string was empty!"-> else return $ length s->->-- Prints result of the string length calculation.->reportResult :: Either String Int -> IO ()->reportResult (Right len) = putStrLn ("The length of the string is " ++ (show len))->reportResult (Left e) = putStrLn ("Length calculation failed with error: " ++ (show e))--}
Control/Monad/Error/Class.hs view
@@ -1,5 +1,12 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE Safe #-}+-- Needed because the CPSed versions of Writer and State are secretly State+-- wrappers, which don't force such constraints, even though they should legally+-- be there.+{-# OPTIONS_GHC -Wno-redundant-constraints #-} {- | Module : Control.Monad.Error.Class@@ -36,35 +43,40 @@ Andy Gill (<http://web.cecs.pdx.edu/~andy/>) -} module Control.Monad.Error.Class (- Error(..), MonadError(..),+ liftEither,+ tryError,+ withError,+ handleError,+ onError,+ mapError,+ modifyError, ) where -import Control.Monad.Trans.Except (Except(..), ExceptT)-import Control.Monad.Trans.Error (Error(..), ErrorT)-import qualified Control.Monad.Trans.Except as ExceptT (throwE, catchE)-import qualified Control.Monad.Trans.Error as ErrorT (throwError, catchError)-import Control.Monad.Trans.Identity as Identity-import Control.Monad.Trans.List as List-import Control.Monad.Trans.Maybe as Maybe-import Control.Monad.Trans.Reader as Reader-import Control.Monad.Trans.RWS.Lazy as LazyRWS-import Control.Monad.Trans.RWS.Strict as StrictRWS-import Control.Monad.Trans.State.Lazy as LazyState-import Control.Monad.Trans.State.Strict as StrictState-import Control.Monad.Trans.Writer.Lazy as LazyWriter-import Control.Monad.Trans.Writer.Strict as StrictWriter-+import Control.Monad.Trans.Except (ExceptT)+import qualified Control.Monad.Trans.Except as ExceptT (catchE, runExceptT, throwE)+import Control.Monad.Trans.Identity (IdentityT)+import qualified Control.Monad.Trans.Identity as Identity+import Control.Monad.Trans.Maybe (MaybeT)+import qualified Control.Monad.Trans.Maybe as Maybe+import Control.Monad.Trans.Reader (ReaderT)+import qualified Control.Monad.Trans.Reader as Reader+import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS+import qualified Control.Monad.Trans.RWS.Strict as StrictRWS+import qualified Control.Monad.Trans.State.Lazy as LazyState+import qualified Control.Monad.Trans.State.Strict as StrictState+import qualified Control.Monad.Trans.Writer.Lazy as LazyWriter+import qualified Control.Monad.Trans.Writer.Strict as StrictWriter+import Control.Monad.Trans.Accum (AccumT)+import qualified Control.Monad.Trans.Accum as Accum+import qualified Control.Monad.Trans.RWS.CPS as CPSRWS+import qualified Control.Monad.Trans.Writer.CPS as CPSWriter import Control.Monad.Trans.Class (lift) import Control.Exception (IOException, catch, ioError)-import Control.Monad--#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < 707-import Control.Monad.Instances ()-#endif--import Data.Monoid-import Prelude (Either(..), (.), IO)+import Control.Monad (Monad ((>>=), (>>)))+import Data.Functor.Product (Product(..))+import Data.Monoid (Monoid)+import Prelude (Either (Left, Right), Maybe (Nothing), either, flip, (.), IO, pure, (<$>)) {- | The strategy of combining computations that can throw exceptions@@ -73,14 +85,16 @@ Is parameterized over the type of error information and the monad type constructor.-It is common to use @'Data.Either' String@ as the monad type constructor+It is common to use @'Either' String@ as the monad type constructor for an error monad in which error descriptions take the form of strings. In that case and many other common cases the resulting monad is already defined as an instance of the 'MonadError' class. You can also define your own error type and\/or use a monad type constructor other than @'Either' 'String'@ or @'Either' 'IOError'@.-In these cases you will have to explicitly define instances of the 'Error'-and\/or 'MonadError' classes.+In these cases you will have to explicitly define instances of the 'MonadError'+class.+(If you are using the deprecated "Control.Monad.Error" or+"Control.Monad.Trans.Error", you may also have to define an 'Error' instance.) -} class (Monad m) => MonadError e m | m -> e where -- | Is used within a monadic computation to begin exception processing.@@ -96,11 +110,30 @@ Note that @handler@ and the do-block must have the same return type. -} catchError :: m a -> (e -> m a) -> m a+ {-# MINIMAL throwError, catchError #-} +{- |+Lifts an @'Either' e@ into any @'MonadError' e@.++> do { val <- liftEither =<< action1; action2 }++where @action1@ returns an 'Either' to represent errors.++@since 2.2.2+-}+liftEither :: MonadError e m => Either e a -> m a+liftEither = either throwError pure+ instance MonadError IOException IO where throwError = ioError catchError = catch +{- | @since 2.2.2 -}+instance MonadError () Maybe where+ throwError () = Nothing+ catchError Nothing f = f ()+ catchError x _ = x+ -- --------------------------------------------------------------------------- -- Our parameterizable error monad @@ -109,10 +142,7 @@ Left l `catchError` h = h l Right r `catchError` _ = Right r -instance (Monad m, Error e) => MonadError e (ErrorT e m) where- throwError = ErrorT.throwError- catchError = ErrorT.catchError-+{- | @since 2.2 -} instance Monad m => MonadError e (ExceptT e m) where throwError = ExceptT.throwE catchError = ExceptT.catchE@@ -127,10 +157,6 @@ throwError = lift . throwError catchError = Identity.liftCatch catchError -instance MonadError e m => MonadError e (ListT m) where- throwError = lift . throwError- catchError = List.liftCatch catchError- instance MonadError e m => MonadError e (MaybeT m) where throwError = lift . throwError catchError = Maybe.liftCatch catchError@@ -162,3 +188,108 @@ instance (Monoid w, MonadError e m) => MonadError e (StrictWriter.WriterT w m) where throwError = lift . throwError catchError = StrictWriter.liftCatch catchError++-- | @since 2.3+instance (Monoid w, MonadError e m) => MonadError e (CPSRWS.RWST r w s m) where+ throwError = lift . throwError+ catchError = CPSRWS.liftCatch catchError++-- | @since 2.3+instance (Monoid w, MonadError e m) => MonadError e (CPSWriter.WriterT w m) where+ throwError = lift . throwError+ catchError = CPSWriter.liftCatch catchError++-- | @since 2.3+instance+ ( Monoid w+ , MonadError e m+ ) => MonadError e (AccumT w m) where+ throwError = lift . throwError+ catchError = Accum.liftCatch catchError++-- | @since 2.3.2+instance (MonadError e m, MonadError e n) => MonadError e (Product m n) where+ throwError e = Pair (throwError e) (throwError e)+ catchError (Pair ma na) f = Pair (catchError ma (productFst . f)) (catchError na (productSnd . f))+ where+ productFst (Pair a _) = a+ productSnd (Pair _ b) = b++-- | 'MonadError' analogue to the 'Control.Exception.try' function.+--+-- @since 2.3+tryError :: MonadError e m => m a -> m (Either e a)+tryError action = (Right <$> action) `catchError` (pure . Left)++-- | 'MonadError' analogue to the 'withExceptT' function.+-- Modify the value (but not the type) of an error. The type is+-- fixed because of the functional dependency @m -> e@. If you need+-- to change the type of @e@ use 'mapError' or 'modifyError'.+--+-- @since 2.3+withError :: MonadError e m => (e -> e) -> m a -> m a+withError f = handleError (throwError . f)++-- | As 'handle' is flipped 'Control.Exception.catch', 'handleError'+-- is flipped 'catchError'.+--+-- @since 2.3+handleError :: MonadError e m => (e -> m a) -> m a -> m a+handleError = flip catchError++-- | If an action throws an error, run a second action and rethrow the error.+-- If the second action also throws an error, it takes precedence. Do not run+-- the second action at all if the first succeeds.+--+-- @since 2.3.2+onError :: MonadError e m => m a -> m b -> m a+onError action1 action2 = action1 `catchError` \e -> action2 >> throwError e++-- | 'MonadError' analogue of the 'mapExceptT' function. The+-- computation is unwrapped, a function is applied to the @Either@, and+-- the result is lifted into the second 'MonadError' instance.+--+-- @since 2.3+mapError :: (MonadError e m, MonadError e' n) => (m (Either e a) -> n (Either e' b)) -> m a -> n b+mapError f action = f (tryError action) >>= liftEither++{- |+A different 'MonadError' analogue to the 'withExceptT' function.+Modify the value (and possibly the type) of an error in an @ExceptT@-transformed+monad, while stripping the @ExceptT@ layer.++This is useful for adapting the 'MonadError' constraint of a computation.++For example:++> data DatabaseError = ...+>+> performDatabaseQuery :: (MonadError DatabaseError m, ...) => m PersistedValue+>+> data AppError+> = MkDatabaseError DatabaseError+> | ...+>+> app :: (MonadError AppError m, ...) => m ()++Given these types, @performDatabaseQuery@ cannot be used directly inside+@app@, because the error types don't match. Using 'modifyError', an equivalent+function with a different error type can be constructed:++> performDatabaseQuery' :: (MonadError AppError m, ...) => m PersistedValue+> performDatabaseQuery' = modifyError MkDatabaseError performDatabaseQuery++Since the error types do match, @performDatabaseQuery'@ _can_ be used in @app@,+assuming all other constraints carry over.++This works by instantiating the @m@ in the type of @performDatabaseQuery@ to+@ExceptT DatabaseError m'@, which satisfies the @MonadError DatabaseError@+constraint. Immediately, the @ExceptT DatabaseError@ layer is unwrapped,+producing 'Either' a @DatabaseError@ or a @PersistedValue@. If it's the former,+the error is wrapped in @MkDatabaseError@ and re-thrown in the inner monad,+otherwise the result value is returned.++@since 2.3.1+-}+modifyError :: MonadError e' m => (e -> e') -> ExceptT e m a -> m a+modifyError f m = ExceptT.runExceptT m >>= either (throwError . f) pure
+ Control/Monad/Except.hs view
@@ -0,0 +1,153 @@+{-# LANGUAGE Safe #-}+{- |+Module : Control.Monad.Except+Copyright : (c) Michael Weber <michael.weber@post.rwth-aachen.de> 2001,+ (c) Jeff Newbern 2003-2006,+ (c) Andriy Palamarchuk 2006+License : BSD-style (see the file LICENSE)++Maintainer : libraries@haskell.org+Stability : experimental+Portability : non-portable (multi-parameter type classes)++[Computation type:] Computations which may fail or throw exceptions.++[Binding strategy:] Failure records information about the cause\/location+of the failure. Failure values bypass the bound function,+other values are used as inputs to the bound function.++[Useful for:] Building computations from sequences of functions that may fail+or using exception handling to structure error handling.++[Example type:] @'Either' String a@++The Error monad (also called the Exception monad).++@since 2.2.1+-}++{-+ Rendered by Michael Weber <mailto:michael.weber@post.rwth-aachen.de>,+ inspired by the Haskell Monad Template Library from+ Andy Gill (<http://web.cecs.pdx.edu/~andy/>)+-}+module Control.Monad.Except+ (+ -- * Warning+ -- $warning+ -- * Monads with error handling+ Error.MonadError(..),+ Error.liftEither,+ Error.tryError,+ Error.withError,+ Error.handleError,+ Error.onError,+ Error.mapError,+ Error.modifyError,+ -- * The ExceptT monad transformer+ Except.ExceptT(ExceptT),+ Except.Except,+ Except.runExceptT,+ Except.mapExceptT,+ Except.withExceptT,+ Except.runExcept,+ Except.mapExcept,+ Except.withExcept,+ -- * Example 1: Custom Error Data Type+ -- $customErrorExample++ -- * Example 2: Using ExceptT Monad Transformer+ -- $ExceptTExample+ ) where++import qualified Control.Monad.Error.Class as Error+import qualified Control.Monad.Trans.Except as Except++{- $warning+Please do not confuse 'ExceptT' and 'throwError' with 'Control.Exception.Exception' /+'Control.Exception.SomeException' and 'Control.Exception.catch', respectively. The latter+are for exceptions built into GHC, by default, and are mostly used from within the IO monad.+They do not interact with the \"exceptions\" in this package at all. This package allows you+to define a new kind of exception control mechanism which does not necessarily need your code to+be placed in the IO monad.++In short, all \"catching\" mechanisms in this library will be unable to catch exceptions thrown+by functions in the "Control.Exception" module, and vice-versa.+-}++{- $customErrorExample+Here is an example that demonstrates the use of a custom error data type with+the 'throwError' and 'catchError' exception mechanism from 'MonadError'.+The example throws an exception if the user enters an empty string+or a string longer than 5 characters. Otherwise it prints length of the string.++>-- This is the type to represent length calculation error.+>data LengthError = EmptyString -- Entered string was empty.+> | StringTooLong Int -- A string is longer than 5 characters.+> -- Records a length of the string.+> | OtherError String -- Other error, stores the problem description.+>+>-- Converts LengthError to a readable message.+>instance Show LengthError where+> show EmptyString = "The string was empty!"+> show (StringTooLong len) =+> "The length of the string (" ++ (show len) ++ ") is bigger than 5!"+> show (OtherError msg) = msg+>+>-- For our monad type constructor, we use Either LengthError+>-- which represents failure using Left LengthError+>-- or a successful result of type a using Right a.+>type LengthMonad = Either LengthError+>+>main = do+> putStrLn "Please enter a string:"+> s <- getLine+> reportResult (calculateLength s)+>+>-- Attempts to calculate length and throws an error if the provided string is+>-- empty or longer than 5 characters.+>-- (Throwing an error in this monad means returning a 'Left'.)+>calculateLength :: String -> LengthMonad Int+>calculateLength [] = throwError EmptyString+>calculateLength s | len > 5 = throwError (StringTooLong len)+> | otherwise = return len+> where len = length s+>+>-- Prints result of the string length calculation.+>reportResult :: LengthMonad Int -> IO ()+>reportResult (Right len) = putStrLn ("The length of the string is " ++ (show len))+>reportResult (Left e) = putStrLn ("Length calculation failed with error: " ++ (show e))+-}++{- $ExceptTExample+@'ExceptT'@ monad transformer can be used to add error handling to another monad.+Here is an example how to combine it with an @IO@ monad:++>import Control.Monad.Except+>+>-- An IO monad which can return String failure.+>-- It is convenient to define the monad type of the combined monad,+>-- especially if we combine more monad transformers.+>type LengthMonad = ExceptT String IO+>+>main = do+> -- runExceptT removes the ExceptT wrapper+> r <- runExceptT calculateLength+> reportResult r+>+>-- Asks user for a non-empty string and returns its length.+>-- Throws an error if user enters an empty string.+>calculateLength :: LengthMonad Int+>calculateLength = do+> -- all the IO operations have to be lifted to the IO monad in the monad stack+> liftIO $ putStrLn "Please enter a non-empty string: "+> s <- liftIO getLine+> if null s+> then throwError "The string was empty!"+> else return $ length s+>+>-- Prints result of the string length calculation.+>reportResult :: Either String Int -> IO ()+>reportResult (Right len) = putStrLn ("The length of the string is " ++ (show len))+>reportResult (Left e) = putStrLn ("Length calculation failed with error: " ++ (show e))+-}
Control/Monad/Identity.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} {- | Module : Control.Monad.Identity Copyright : (c) Andy Gill 2001,@@ -13,7 +14,7 @@ [Computation type:] Simple function application. [Binding strategy:] The bound function is applied to the input value.-@'Identity' x >>= f == 'Identity' (f x)@+@'Identity' x >>= f == f x@ [Useful for:] Monads can be derived from monad transformers applied to the 'Identity' monad.@@ -34,11 +35,8 @@ module Control.Monad.Identity ( module Data.Functor.Identity,-- module Control.Monad,- module Control.Monad.Fix,+ module Control.Monad.Trans.Identity, ) where -import Control.Monad-import Control.Monad.Fix import Data.Functor.Identity+import Control.Monad.Trans.Identity
− Control/Monad/List.hs
@@ -1,25 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Control.Monad.List--- Copyright : (c) Andy Gill 2001,--- (c) Oregon Graduate Institute of Science and Technology, 2001--- License : BSD-style (see the file LICENSE)------ Maintainer : libraries@haskell.org--- Stability : experimental--- Portability : portable------ The List monad.-----------------------------------------------------------------------------------module Control.Monad.List (- ListT(..),- mapListT,- module Control.Monad,- module Control.Monad.Trans,- ) where--import Control.Monad-import Control.Monad.Trans-import Control.Monad.Trans.List
Control/Monad/RWS.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE Safe #-}+ ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.RWS
+ Control/Monad/RWS/CPS.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE Safe #-}+-----------------------------------------------------------------------------+-- |+-- Module : Control.Monad.RWS.Strict+-- Copyright : (c) Andy Gill 2001,+-- (c) Oregon Graduate Institute of Science and Technology, 2001+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : libraries@haskell.org+-- Stability : experimental+-- Portability : non-portable (multi-param classes, functional dependencies)+--+-- Strict RWS monad that uses continuation-passing-style to achieve constant+-- space usage.+--+-- Inspired by the paper+-- /Functional Programming with Overloading and Higher-Order Polymorphism/,+-- Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>)+-- Advanced School of Functional Programming, 1995.+--+-- /Since: mtl-2.3, transformers-0.5.6/+-----------------------------------------------------------------------------++module Control.Monad.RWS.CPS (+ -- * The RWS monad+ RWS,+ rws,+ runRWS,+ evalRWS,+ execRWS,+ mapRWS,+ withRWS,+ -- * The RWST monad transformer+ RWST,+ runRWST,+ evalRWST,+ execRWST,+ mapRWST,+ withRWST,+ -- * Strict Reader-writer-state monads+ module Control.Monad.RWS.Class,+ module Control.Monad.Trans,+ ) where++import Control.Monad.RWS.Class++import Control.Monad.Trans+import Control.Monad.Trans.RWS.CPS (+ RWS, rws, runRWS, evalRWS, execRWS, mapRWS, withRWS,+ RWST, runRWST, evalRWST, execRWST, mapRWST, withRWST)
Control/Monad/RWS/Class.hs view
@@ -1,5 +1,9 @@-{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE MultiParamTypeClasses #-} -- Search for UndecidableInstances to see why this is needed+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- |@@ -31,30 +35,34 @@ import Control.Monad.State.Class import Control.Monad.Writer.Class -import Control.Monad.Trans.Class-import Control.Monad.Trans.Error(Error, ErrorT)-import Control.Monad.Trans.Except(ExceptT)-import Control.Monad.Trans.Maybe(MaybeT)-import Control.Monad.Trans.Identity(IdentityT)-import Control.Monad.Trans.RWS.Lazy as Lazy (RWST)+import Control.Monad.Trans.Except (ExceptT)+import Control.Monad.Trans.Maybe (MaybeT)+import Control.Monad.Trans.Identity (IdentityT)+import qualified Control.Monad.Trans.RWS.CPS as CPS (RWST)+import qualified Control.Monad.Trans.RWS.Lazy as Lazy (RWST) import qualified Control.Monad.Trans.RWS.Strict as Strict (RWST)--import Data.Monoid+import Data.Functor.Product (Product(..)) class (Monoid w, MonadReader r m, MonadWriter w m, MonadState s m) => MonadRWS r w s m | m -> r, m -> w, m -> s +-- | @since 2.3+instance (Monoid w, Monad m) => MonadRWS r w s (CPS.RWST r w s m)+ instance (Monoid w, Monad m) => MonadRWS r w s (Lazy.RWST r w s m) instance (Monoid w, Monad m) => MonadRWS r w s (Strict.RWST r w s m)- + --------------------------------------------------------------------------- -- Instances for other mtl transformers -- -- All of these instances need UndecidableInstances, -- because they do not satisfy the coverage condition. +-- | @since 2.2 instance MonadRWS r w s m => MonadRWS r w s (ExceptT e m)-instance (Error e, MonadRWS r w s m) => MonadRWS r w s (ErrorT e m) instance MonadRWS r w s m => MonadRWS r w s (IdentityT m) instance MonadRWS r w s m => MonadRWS r w s (MaybeT m)++-- | @since 2.3.2+instance (MonadRWS r w s m, MonadRWS r w s n) => MonadRWS r w s (Product m n)
Control/Monad/RWS/Lazy.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.RWS.Lazy@@ -27,17 +28,15 @@ mapRWS, withRWS, -- * The RWST monad transformer- RWST(..),+ RWST(RWST),+ runRWST, evalRWST, execRWST, mapRWST, withRWST, -- * Lazy Reader-writer-state monads module Control.Monad.RWS.Class,- module Control.Monad,- module Control.Monad.Fix, module Control.Monad.Trans,- module Data.Monoid, ) where import Control.Monad.RWS.Class@@ -45,8 +44,4 @@ import Control.Monad.Trans import Control.Monad.Trans.RWS.Lazy ( RWS, rws, runRWS, evalRWS, execRWS, mapRWS, withRWS,- RWST(..), evalRWST, execRWST, mapRWST, withRWST)--import Control.Monad-import Control.Monad.Fix-import Data.Monoid+ RWST(RWST), runRWST, evalRWST, execRWST, mapRWST, withRWST)
Control/Monad/RWS/Strict.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.RWS.Strict@@ -27,26 +28,20 @@ mapRWS, withRWS, -- * The RWST monad transformer- RWST(..),+ RWST(RWST),+ runRWST, evalRWST, execRWST, mapRWST, withRWST, -- * Strict Reader-writer-state monads module Control.Monad.RWS.Class,- module Control.Monad,- module Control.Monad.Fix, module Control.Monad.Trans,- module Data.Monoid, ) where import Control.Monad.RWS.Class- import Control.Monad.Trans+ import Control.Monad.Trans.RWS.Strict ( RWS, rws, runRWS, evalRWS, execRWS, mapRWS, withRWS,- RWST(..), evalRWST, execRWST, mapRWST, withRWST)--import Control.Monad-import Control.Monad.Fix-import Data.Monoid+ RWST(RWST), runRWST, evalRWST, execRWST, mapRWST, withRWST)
Control/Monad/Reader.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} {- | Module : Control.Monad.Reader Copyright : (c) Andy Gill 2001,@@ -37,19 +38,18 @@ module Control.Monad.Reader ( -- * MonadReader class- MonadReader(..),- asks,+ MonadReader.MonadReader(..),+ MonadReader.asks, -- * The Reader monad Reader, runReader, mapReader, withReader, -- * The ReaderT monad transformer- ReaderT(..),+ ReaderT(ReaderT),+ runReaderT, mapReaderT, withReaderT,- module Control.Monad,- module Control.Monad.Fix, module Control.Monad.Trans, -- * Example 1: Simple Reader Usage -- $simpleReaderExample@@ -61,15 +61,12 @@ -- $ReaderTExample ) where -import Control.Monad.Reader.Class+import qualified Control.Monad.Reader.Class as MonadReader+import Control.Monad.Trans import Control.Monad.Trans.Reader ( Reader, runReader, mapReader, withReader,- ReaderT(..), mapReaderT, withReaderT)-import Control.Monad.Trans--import Control.Monad-import Control.Monad.Fix+ ReaderT(ReaderT), runReaderT, mapReaderT, withReaderT) {- $simpleReaderExample @@ -79,8 +76,12 @@ You can see how to run a Reader monad and retrieve data from it with 'runReader', how to access the Reader data with 'ask' and 'asks'. -> type Bindings = Map String Int;+>import Control.Monad.Reader+>import Data.Map (Map)+>import qualified Data.Map as Map >+>type Bindings = Map String Int+> >-- Returns True if the "count" variable contains correct bindings size. >isCountCorrect :: Bindings -> Bool >isCountCorrect bindings = runReader calc_isCountCorrect bindings@@ -92,22 +93,26 @@ > bindings <- ask > return (count == (Map.size bindings)) >->-- The selector function to use with 'asks'.+>-- 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)+>lookupVar name bindings = maybe 0 id (Map.lookup name bindings) >->sampleBindings = Map.fromList [("count",3), ("1",1), ("b",2)]+>sampleBindings :: Bindings+>sampleBindings = Map.fromList [("count", 3), ("1", 1), ("b", 2)] >+>main :: IO () >main = do-> putStr $ "Count is correct for bindings " ++ (show sampleBindings) ++ ": ";-> putStrLn $ show (isCountCorrect sampleBindings);+> putStr $ "Count is correct for bindings " ++ (show sampleBindings) ++ ": "+> putStrLn $ show (isCountCorrect sampleBindings) -} {- $localExample Shows how to modify Reader content with 'local'. +>import Control.Monad.Reader+> >calculateContentLen :: Reader String Int >calculateContentLen = do > content <- ask@@ -117,6 +122,7 @@ >calculateModifiedContentLen :: Reader String Int >calculateModifiedContentLen = local ("Prefix " ++) calculateContentLen >+>main :: IO () >main = do > let s = "12345"; > let modifiedLen = runReader calculateModifiedContentLen s@@ -129,15 +135,17 @@ Now you are thinking: 'Wow, what a great monad! I wish I could use Reader functionality in MyFavoriteComplexMonad!'. Don't worry.-This can be easy done with the 'ReaderT' monad transformer.+This can be easily done with the 'ReaderT' monad transformer. This example shows how to combine @ReaderT@ with the IO monad. +>import Control.Monad.Reader+> >-- The Reader/IO combined monad, where Reader stores a string. >printReaderContent :: ReaderT String IO () >printReaderContent = do > content <- ask > liftIO $ putStrLn ("The Reader Content: " ++ content) >->main = do-> runReaderT printReaderContent "Some Content"+>main :: IO ()+>main = runReaderT printReaderContent "Some Content" -}
Control/Monad/Reader/Class.hs view
@@ -1,5 +1,13 @@-{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE MultiParamTypeClasses #-} -- Search for UndecidableInstances to see why this is needed+{-# LANGUAGE UndecidableInstances #-}+-- Needed because the CPSed versions of Writer and State are secretly State+-- wrappers, which don't force such constraints, even though they should legally+-- be there.+{-# OPTIONS_GHC -Wno-redundant-constraints #-} {- | Module : Control.Monad.Reader.Class Copyright : (c) Andy Gill 2001,@@ -42,24 +50,26 @@ asks, ) where -import Control.Monad.Trans.Cont as Cont-import Control.Monad.Trans.Except-import Control.Monad.Trans.Error-import Control.Monad.Trans.Identity-import Control.Monad.Trans.List-import Control.Monad.Trans.Maybe+import qualified Control.Monad.Trans.Cont as Cont+import Control.Monad.Trans.Cont (ContT)+import Control.Monad.Trans.Except (ExceptT, mapExceptT)+import Control.Monad.Trans.Identity (IdentityT, mapIdentityT)+import Control.Monad.Trans.Maybe (MaybeT, mapMaybeT) import Control.Monad.Trans.Reader (ReaderT)-import qualified Control.Monad.Trans.Reader as ReaderT (ask, local, reader)-import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS (RWST, ask, local, reader)-import qualified Control.Monad.Trans.RWS.Strict as StrictRWS (RWST, ask, local, reader)-import Control.Monad.Trans.State.Lazy as Lazy-import Control.Monad.Trans.State.Strict as Strict-import Control.Monad.Trans.Writer.Lazy as Lazy-import Control.Monad.Trans.Writer.Strict as Strict-+import qualified Control.Monad.Trans.Reader as ReaderT+import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS+import qualified Control.Monad.Trans.RWS.Strict as StrictRWS+import qualified Control.Monad.Trans.State.Lazy as Lazy+import qualified Control.Monad.Trans.State.Strict as Strict+import qualified Control.Monad.Trans.Writer.Lazy as Lazy+import qualified Control.Monad.Trans.Writer.Strict as Strict+import Control.Monad.Trans.Accum (AccumT)+import qualified Control.Monad.Trans.Accum as Accum+import Control.Monad.Trans.Select (SelectT (SelectT), runSelectT)+import qualified Control.Monad.Trans.RWS.CPS as CPSRWS+import qualified Control.Monad.Trans.Writer.CPS as CPS import Control.Monad.Trans.Class (lift)-import Control.Monad-import Data.Monoid+import Data.Functor.Product (Product(..)) -- ---------------------------------------------------------------------------- -- class MonadReader@@ -69,8 +79,10 @@ -- Note, the partially applied function type @(->) r@ is a simple reader monad. -- See the @instance@ declaration below. class Monad m => MonadReader r m | m -> r where+ {-# MINIMAL (ask | reader), local #-} -- | Retrieves the monad environment. ask :: m r+ ask = reader id -- | Executes a computation in a modified environment. local :: (r -> r) -- ^ The function to modify the environment.@@ -103,6 +115,12 @@ local = ReaderT.local reader = ReaderT.reader +-- | @since 2.3+instance (Monad m, Monoid w) => MonadReader r (CPSRWS.RWST r w s m) where+ ask = CPSRWS.ask+ local = CPSRWS.local+ reader = CPSRWS.reader+ instance (Monad m, Monoid w) => MonadReader r (LazyRWS.RWST r w s m) where ask = LazyRWS.ask local = LazyRWS.local@@ -124,11 +142,7 @@ local = Cont.liftLocal ask local reader = lift . reader -instance (Error e, MonadReader r m) => MonadReader r (ErrorT e m) where- ask = lift ask- local = mapErrorT . local- reader = lift . reader-+{- | @since 2.2 -} instance MonadReader r m => MonadReader r (ExceptT e m) where ask = lift ask local = mapExceptT . local@@ -139,11 +153,6 @@ local = mapIdentityT . local reader = lift . reader -instance MonadReader r m => MonadReader r (ListT m) where- ask = lift ask- local = mapListT . local- reader = lift . reader- instance MonadReader r m => MonadReader r (MaybeT m) where ask = lift ask local = mapMaybeT . local@@ -159,6 +168,12 @@ local = Strict.mapStateT . local reader = lift . reader +-- | @since 2.3+instance (Monoid w, MonadReader r m) => MonadReader r (CPS.WriterT w m) where+ ask = lift ask+ local = CPS.mapWriterT . local+ reader = lift . reader+ instance (Monoid w, MonadReader r m) => MonadReader r (Lazy.WriterT w m) where ask = lift ask local = Lazy.mapWriterT . local@@ -168,3 +183,28 @@ ask = lift ask local = Strict.mapWriterT . local reader = lift . reader++-- | @since 2.3+instance+ ( Monoid w+ , MonadReader r m+ ) => MonadReader r (AccumT w m) where+ ask = lift ask+ local = Accum.mapAccumT . local+ reader = lift . reader++-- | @since 2.3+instance+ ( MonadReader r' m+ ) => MonadReader r' (SelectT r m) where+ ask = lift ask+ -- there is no Select.liftLocal+ local f m = SelectT $ \c -> do+ r <- ask+ local f (runSelectT m (local (const r) . c))+ reader = lift . reader++-- | @since 2.3.2+instance (MonadReader r m, MonadReader r n) => MonadReader r (Product m n) where+ ask = Pair ask ask+ local f (Pair ma na) = Pair (local f ma) (local f na)
+ Control/Monad/Select.hs view
@@ -0,0 +1,316 @@+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE UndecidableInstances #-}+-- Later GHCs infer DerivingVia as not Safe+-- We just downgrade to Trustworthy and go fish+{-# OPTIONS_GHC -Wno-trustworthy-safe #-}++-- | Module: Control.Monad.Select+-- Copyright: (C) Koz Ross 2022+-- License: BSD-3-Clause (see the LICENSE file)+-- Maintainer: koz.ross@retro-freedom.nz+-- Stability: Experimental+-- Portability: GHC only+--+-- [Computation type:] Backtracking search, with @r@ as a \'ranking\' or+-- \'evaluation\' type.+--+-- [Binding strategy:] Binding a function to a monadic value \'chains together\'+-- strategies; having seen the result of one search, decide which policy to use+-- to continue.+--+-- [Useful for:] Search problems.+--+-- [Zero and plus:] None.+--+-- [Example type:] @'Control.Monad.Trans.Select.Select' r a@+--+-- = A note on commutativity+--+-- Some effects are /commutative/: it doesn't matter which you resolve first, as+-- all possible orderings of commutative effects are isomorphic. Consider, for+-- example, the reader and state effects, as exemplified by 'ReaderT' and+-- 'StrictState.StateT' respectively. If we have+-- @'ReaderT' r ('StrictState.State' s) a@, this is+-- effectively @r -> 'StrictState.State' s a ~ r -> s -> (a, s)@; if we instead have+-- @'StrictState.StateT' s ('Control.Monad.Trans.Reader.Reader' r) a@, this is effectively+-- @s -> 'Control.Monad.Trans.Reader' r (a, s) ~ s -> r -> (a, s)@. Since we+-- can always reorder function arguments (for example, using 'flip', as in+-- this case) without changing the result, these are+-- isomorphic, showing that reader and state are /commutative/, or, more+-- precisely, /commute with each other/.+--+-- However, this isn't generally the case. Consider instead the error and state+-- effects, as exemplified by 'MaybeT' and 'StrictState.StateT' respectively.+-- If we have @'MaybeT' ('Control.Monad.Trans.State.Strict.State' s) a@, this+-- is effectively @'State' s ('Maybe' a) ~ s -> ('Maybe' a, s)@: put simply,+-- the error can occur only in the /result/, but+-- not the state, which always \'survives\'. On the other hand, if we have+-- @'StrictState.StateT' s 'Maybe' a@, this is instead @s -> 'Maybe' (a, s)@: here,+-- if we error, we lose /both/ the state and the result! Thus, error and state effects+-- do /not/ commute with each other.+--+-- As the MTL is capability-based, we support any ordering of non-commutative+-- effects on an equal footing. Indeed, if you wish to use+-- 'Control.Monad.State.Class.MonadState', for+-- example, whether your final monadic stack ends up being @'MaybeT'+-- ('Control.Monad.Trans.State.Strict.State' s)+-- a@, @'StrictState.StateT' s 'Maybe' a@, or anything else, you will be able to write your+-- desired code without having to consider such differences. However, the way we+-- /implement/ these capabilities for any given transformer (or rather, any+-- given transformed stack) /is/ affected by this ordering unless the effects in+-- question are commutative.+--+-- We note in this module which effects the accumulation effect does and doesn't+-- commute with; we also note on implementations with non-commutative+-- transformers what the outcome will be. Note that, depending on how the+-- \'inner monad\' is structured, this may be more complex than we note: we+-- describe only what impact the \'outer effect\' has, not what else might be in+-- the stack.+--+-- = Commutativity of selection+--+-- The selection effect commutes with the identity effect ('IdentityT'), but+-- nothing else.+module Control.Monad.Select+ ( -- * Type class+ MonadSelect (..),++ -- * Lifting helper type+ LiftingSelect (..),+ )+where++import Control.Monad.Trans.Accum (AccumT)+import Control.Monad.Trans.Class (MonadTrans (lift))+import Control.Monad.Trans.Cont (ContT)+import Control.Monad.Trans.Except (ExceptT)+import Control.Monad.Trans.Identity (IdentityT)+import Control.Monad.Trans.Maybe (MaybeT)+import qualified Control.Monad.Trans.RWS.CPS as CPSRWS+import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS+import qualified Control.Monad.Trans.RWS.Strict as StrictRWS+import Control.Monad.Trans.Reader (ReaderT)+import Control.Monad.Trans.Select (SelectT)+import qualified Control.Monad.Trans.Select as Select+import qualified Control.Monad.Trans.State.Lazy as LazyState+import qualified Control.Monad.Trans.State.Strict as StrictState+import qualified Control.Monad.Trans.Writer.CPS as CPSWriter+import qualified Control.Monad.Trans.Writer.Lazy as LazyWriter+import qualified Control.Monad.Trans.Writer.Strict as StrictWriter+import Data.Functor.Identity (Identity)+import Data.Kind (Type)++-- | The capability to search with backtracking. Essentially describes a+-- \'policy function\': given the state of the search (and a \'ranking\' or+-- \'evaluation\' of each possible result so far), pick the result that's+-- currently best.+--+-- = Laws+--+-- Any instance of 'MonadSelect' must follow these laws:+--+-- * @'select' ('const' x)@ @=@ @'pure' x@+-- * @'select' f '*>' 'select' g@ @=@ @'select' g@+--+-- @since 2.3+class (Monad m) => MonadSelect r m | m -> r where+ select :: ((a -> r) -> a) -> m a++-- | @since 2.3+instance MonadSelect r (SelectT r Identity) where+ select = Select.select++-- | \'Extends\' the possibilities considered by @m@ to include 'Nothing'; this+-- means that 'Nothing' gains a \'rank\' (namely, a value of @r@), and the+-- potential result could also be 'Nothing'.+--+-- @since 2.3+deriving via+ (LiftingSelect MaybeT m)+ instance+ (MonadSelect r m) =>+ MonadSelect r (MaybeT m)++-- | The continuation describes a way of choosing a \'search\' or \'ranking\'+-- strategy for @r@, based on a \'ranking\' using @r'@, given any @a@. We then+-- get a \'search\' strategy for @r@.+--+-- @since 2.3+deriving via+ (LiftingSelect (ContT r) m)+ instance+ (MonadSelect r' m) =>+ MonadSelect r' (ContT r m)++-- | \'Extends\' the possibilities considered by @m@ to include every value of+-- @e@; this means that the potential result could be either a 'Left' (making it+-- a choice of type @e@) or a 'Right' (making it a choice of type @a@).+--+-- @since 2.3+deriving via+ (LiftingSelect (ExceptT e) m)+ instance+ (MonadSelect r m) =>+ MonadSelect r (ExceptT e m)++-- | @since 2.3+deriving via+ (LiftingSelect IdentityT m)+ instance+ (MonadSelect r m) =>+ MonadSelect r (IdentityT m)++-- | Provides a read-only environment of type @r@ to the \'strategy\' function.+-- However, the \'ranking\' function (or more accurately, representation) has no+-- access to @r@. Put another way, you can influence what values get chosen by+-- changing @r@, but not how solutions are ranked.+--+-- @since 2.3+deriving via+ (LiftingSelect (ReaderT r) m)+ instance+ (MonadSelect r' m) =>+ MonadSelect r' (ReaderT r m)++-- | \'Readerizes\' the state: the \'ranking\' function can /see/ a value of+-- type @s@, but not modify it. Effectively, can be thought of as \'extending\'+-- the \'ranking\' by all values in @s@, but /which/ @s@ gets given to any rank+-- calls is predetermined by the \'outer state\' (and cannot change).+--+-- @since 2.3+deriving via+ (LiftingSelect (LazyState.StateT s) m)+ instance+ (MonadSelect w m) =>+ MonadSelect w (LazyState.StateT s m)++-- | \'Readerizes\' the state: the \'ranking\' function can /see/ a value of+-- type @s@, but not modify it. Effectively, can be thought of as \'extending\'+-- the \'ranking\' by all values in @s@, but /which/ @s@ gets given to any rank+-- calls is predetermined by the \'outer state\' (and cannot change).+--+-- @since 2.3+deriving via+ (LiftingSelect (StrictState.StateT s) m)+ instance+ (MonadSelect w m) =>+ MonadSelect w (StrictState.StateT s m)++-- | \'Readerizes\' the writer: the \'ranking\' function can see the value+-- that's been accumulated (of type @w@), but can't add anything to the log.+-- Effectively, can be thought of as \'extending\' the \'ranking\' by all values+-- of @w@, but /which/ @w@ gets given to any rank calls is predetermined by the+-- \'outer writer\' (and cannot change).+--+-- @since 2.3+deriving via+ (LiftingSelect (CPSWriter.WriterT w) m)+ instance+ (MonadSelect w' m) =>+ MonadSelect w' (CPSWriter.WriterT w m)++-- | \'Readerizes\' the writer: the \'ranking\' function can see the value+-- that's been accumulated (of type @w@), but can't add anything to the log.+-- Effectively, can be thought of as \'extending\' the \'ranking\' by all values+-- of @w@, but /which/ @w@ gets given to any rank calls is predetermined by the+-- \'outer writer\' (and cannot change).+--+-- @since 2.3+deriving via+ (LiftingSelect (LazyWriter.WriterT w) m)+ instance+ (MonadSelect w' m, Monoid w) =>+ MonadSelect w' (LazyWriter.WriterT w m)++-- | \'Readerizes\' the writer: the \'ranking\' function can see the value+-- that's been accumulated (of type @w@), but can't add anything to the log.+-- Effectively, can be thought of as \'extending\' the \'ranking\' by all values+-- of @w@, but /which/ @w@ gets given to any rank calls is predetermined by the+-- \'outer writer\' (and cannot change).+--+-- @since 2.3+deriving via+ (LiftingSelect (StrictWriter.WriterT w) m)+ instance+ (MonadSelect w' m, Monoid w) =>+ MonadSelect w' (StrictWriter.WriterT w m)++-- | A combination of an \'outer\' 'ReaderT', 'WriterT' and 'StateT'. In short,+-- you get a value of type @r@ which can influence what gets picked, but not how+-- anything is ranked, and the \'ranking\' function gets access to an @s@ and a+-- @w@, but can modify neither.+--+-- @since 2.3+deriving via+ (LiftingSelect (CPSRWS.RWST r w s) m)+ instance+ (MonadSelect w' m) =>+ MonadSelect w' (CPSRWS.RWST r w s m)++-- | A combination of an \'outer\' 'ReaderT', 'WriterT' and 'StateT'. In short,+-- you get a value of type @r@ which can influence what gets picked, but not how+-- anything is ranked, and the \'ranking\' function gets access to an @s@ and a+-- @w@, but can modify neither.+--+-- @since 2.3+deriving via+ (LiftingSelect (LazyRWS.RWST r w s) m)+ instance+ (MonadSelect w' m, Monoid w) =>+ MonadSelect w' (LazyRWS.RWST r w s m)++-- | A combination of an \'outer\' 'ReaderT', 'WriterT' and 'StateT'. In short,+-- you get a value of type @r@ which can influence what gets picked, but not how+-- anything is ranked, and the \'ranking\' function gets access to an @s@ and a+-- @w@, but can modify neither.+--+-- @since 2.3+deriving via+ (LiftingSelect (StrictRWS.RWST r w s) m)+ instance+ (MonadSelect w' m, Monoid w) =>+ MonadSelect w' (StrictRWS.RWST r w s m)++-- | \'Readerizes\' the accumulator: the \'ranking\' function can see the value+-- that has been accumulated (of type @w@), but can't add anything to it.+-- Effectively, can be thought of as \'extending\' the \'ranking\' by all values+-- of @w@, but /which/ @w@ gets given to any rank calls is predetermined by the+-- \'outer accumulation\' (and cannot change).+--+-- @since 2.3+deriving via+ (LiftingSelect (AccumT w) m)+ instance+ (MonadSelect r m, Monoid w) =>+ MonadSelect r (AccumT w m)++-- | A helper type to decrease boilerplate when defining new transformer+-- instances of 'MonadSelect'.+--+-- Most of the instances in this module are derived using this method; for+-- example, our instance of 'ExceptT' is derived as follows:+--+-- > deriving via (LiftingSelect (ExceptT e) m) instance (MonadSelect r m) =>+-- > MonadSelect r (ExceptT e m)+--+-- @since 2.3+newtype LiftingSelect (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) (a :: Type)+ = LiftingSelect (t m a)+ deriving+ ( -- | @since 2.3+ Functor,+ -- | @since 2.3+ Applicative,+ -- | @since 2.3+ Monad+ )+ via (t m)++-- | @since 2.3+instance (MonadTrans t, MonadSelect r m, Monad (t m)) => MonadSelect r (LiftingSelect t m) where+ select f = LiftingSelect . lift $ select f
Control/Monad/State.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.State
Control/Monad/State/Class.hs view
@@ -1,5 +1,13 @@-{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-} -- Search for UndecidableInstances to see why this is needed+{-# LANGUAGE UndecidableInstances #-}+-- Needed because the CPSed versions of Writer and State are secretly State+-- wrappers, which don't force such constraints, even though they should legally+-- be there.+{-# OPTIONS_GHC -Wno-redundant-constraints #-} ----------------------------------------------------------------------------- -- |@@ -28,23 +36,23 @@ gets ) where -import Control.Monad.Trans.Cont-import Control.Monad.Trans.Error-import Control.Monad.Trans.Except-import Control.Monad.Trans.Identity-import Control.Monad.Trans.List-import Control.Monad.Trans.Maybe-import Control.Monad.Trans.Reader-import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS (RWST, get, put, state)-import qualified Control.Monad.Trans.RWS.Strict as StrictRWS (RWST, get, put, state)-import qualified Control.Monad.Trans.State.Lazy as Lazy (StateT, get, put, state)-import qualified Control.Monad.Trans.State.Strict as Strict (StateT, get, put, state)-import Control.Monad.Trans.Writer.Lazy as Lazy-import Control.Monad.Trans.Writer.Strict as Strict-+import Control.Monad.Trans.Cont (ContT)+import Control.Monad.Trans.Except (ExceptT)+import Control.Monad.Trans.Identity (IdentityT)+import Control.Monad.Trans.Maybe (MaybeT) +import Control.Monad.Trans.Reader (ReaderT)+import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS+import qualified Control.Monad.Trans.RWS.Strict as StrictRWS+import qualified Control.Monad.Trans.State.Lazy as Lazy+import qualified Control.Monad.Trans.State.Strict as Strict+import qualified Control.Monad.Trans.Writer.Lazy as Lazy+import qualified Control.Monad.Trans.Writer.Strict as Strict+import Control.Monad.Trans.Accum (AccumT)+import Control.Monad.Trans.Select (SelectT)+import qualified Control.Monad.Trans.RWS.CPS as CPSRWS+import qualified Control.Monad.Trans.Writer.CPS as CPS import Control.Monad.Trans.Class (lift)-import Control.Monad-import Data.Monoid+import Data.Functor.Product (Product(..)) -- --------------------------------------------------------------------------- @@ -65,6 +73,7 @@ let ~(a, s') = f s put s' return a+ {-# MINIMAL state | get, put #-} -- | Monadic state transformer. --@@ -82,8 +91,12 @@ -- | A variant of 'modify' in which the computation is strict in the -- new state.+--+-- @since 2.2 modify' :: MonadState s m => (s -> s) -> m ()-modify' f = state (\s -> let s' = f s in s' `seq` ((), s'))+modify' f = do+ s' <- get+ put $! f s' -- | Gets specific component of the state, using a projection function -- supplied.@@ -102,6 +115,12 @@ put = Strict.put state = Strict.state +-- | @since 2.3+instance (Monad m, Monoid w) => MonadState s (CPSRWS.RWST r w s m) where+ get = CPSRWS.get+ put = CPSRWS.put+ state = CPSRWS.state+ instance (Monad m, Monoid w) => MonadState s (LazyRWS.RWST r w s m) where get = LazyRWS.get put = LazyRWS.put@@ -123,11 +142,7 @@ put = lift . put state = lift . state -instance (Error e, MonadState s m) => MonadState s (ErrorT e m) where- get = lift get- put = lift . put- state = lift . state-+-- | @since 2.2 instance MonadState s m => MonadState s (ExceptT e m) where get = lift get put = lift . put@@ -138,17 +153,18 @@ put = lift . put state = lift . state -instance MonadState s m => MonadState s (ListT m) where+instance MonadState s m => MonadState s (MaybeT m) where get = lift get put = lift . put state = lift . state -instance MonadState s m => MonadState s (MaybeT m) where+instance MonadState s m => MonadState s (ReaderT r m) where get = lift get put = lift . put state = lift . state -instance MonadState s m => MonadState s (ReaderT r m) where+-- | @since 2.3+instance (Monoid w, MonadState s m) => MonadState s (CPS.WriterT w m) where get = lift get put = lift . put state = lift . state@@ -162,3 +178,24 @@ get = lift get put = lift . put state = lift . state++-- | @since 2.3+instance+ ( Monoid w+ , MonadState s m+ ) => MonadState s (AccumT w m) where+ get = lift get+ put = lift . put+ state = lift . state++-- | @since 2.3+instance MonadState s m => MonadState s (SelectT r m) where+ get = lift get+ put = lift . put+ state = lift . state++-- | @since 2.3.2+instance (MonadState s m, MonadState s n) => MonadState s (Product m n) where+ get = Pair get get+ put s = Pair (put s) (put s)+ state sas = Pair (state sas) (state sas)
Control/Monad/State/Lazy.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.State.Lazy@@ -20,10 +21,10 @@ module Control.Monad.State.Lazy ( -- * MonadState class- MonadState(..),- modify,- modify',- gets,+ MonadState.MonadState(..),+ MonadState.modify,+ MonadState.modify',+ MonadState.gets, -- * The State monad State, runState,@@ -32,33 +33,29 @@ mapState, withState, -- * The StateT monad transformer- StateT(..),+ StateT(StateT),+ runStateT, evalStateT, execStateT, mapStateT, withStateT,- module Control.Monad,- module Control.Monad.Fix, module Control.Monad.Trans, -- * Examples -- $examples ) where -import Control.Monad.State.Class-+import qualified Control.Monad.State.Class as MonadState import Control.Monad.Trans+ import Control.Monad.Trans.State.Lazy (State, runState, evalState, execState, mapState, withState,- StateT(..), evalStateT, execStateT, mapStateT, withStateT)--import Control.Monad-import Control.Monad.Fix+ StateT(StateT), runStateT, evalStateT, execStateT, mapStateT, withStateT) -- --------------------------------------------------------------------------- -- $examples -- A function to increment a counter. Taken from the paper -- /Generalising Monads to Arrows/, John--- Hughes (<http://www.math.chalmers.se/~rjmh/>), November 1998:+-- Hughes (<http://www.cse.chalmers.se/~rjmh/Papers/arrows.pdf>), November 1998: -- -- > tick :: State Int Int -- > tick = do n <- get
Control/Monad/State/Strict.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.State.Strict@@ -20,10 +21,10 @@ module Control.Monad.State.Strict ( -- * MonadState class- MonadState(..),- modify,- modify',- gets,+ MonadState.MonadState(..),+ MonadState.modify,+ MonadState.modify',+ MonadState.gets, -- * The State monad State, runState,@@ -32,27 +33,23 @@ mapState, withState, -- * The StateT monad transformer- StateT(..),+ StateT(StateT),+ runStateT, evalStateT, execStateT, mapStateT, withStateT,- module Control.Monad,- module Control.Monad.Fix, module Control.Monad.Trans, -- * Examples -- $examples ) where -import Control.Monad.State.Class-+import qualified Control.Monad.State.Class as MonadState import Control.Monad.Trans+ import Control.Monad.Trans.State.Strict (State, runState, evalState, execState, mapState, withState,- StateT(..), evalStateT, execStateT, mapStateT, withStateT)--import Control.Monad-import Control.Monad.Fix+ StateT(StateT), runStateT, evalStateT, execStateT, mapStateT, withStateT) -- --------------------------------------------------------------------------- -- $examples
Control/Monad/Trans.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.Trans
Control/Monad/Writer.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE Safe #-}+ ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.Writer
+ Control/Monad/Writer/CPS.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE Safe #-}+-----------------------------------------------------------------------------+-- |+-- Module : Control.Monad.Writer.Strict+-- Copyright : (c) Andy Gill 2001,+-- (c) Oregon Graduate Institute of Science and Technology, 2001+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : libraries@haskell.org+-- Stability : experimental+-- Portability : non-portable (multi-param classes, functional dependencies)+--+-- Strict writer monads that use continuation-passing-style to achieve constant+-- space usage.+--+-- Inspired by the paper+-- /Functional Programming with Overloading and Higher-Order Polymorphism/,+-- Mark P Jones (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>)+-- Advanced School of Functional Programming, 1995.+--+-- /Since: mtl-2.3, transformers-0.5.6/+-----------------------------------------------------------------------------++module Control.Monad.Writer.CPS (+ -- * MonadWriter class+ MonadWriter.MonadWriter(..),+ MonadWriter.listens,+ MonadWriter.censor,+ -- * The Writer monad+ Writer,+ runWriter,+ execWriter,+ mapWriter,+ -- * The WriterT monad transformer+ WriterT,+ writerT,+ runWriterT,+ execWriterT,+ mapWriterT,+ module Control.Monad.Trans,+ ) where++import qualified Control.Monad.Writer.Class as MonadWriter+import Control.Monad.Trans+import Control.Monad.Trans.Writer.CPS (+ Writer, runWriter, execWriter, mapWriter,+ WriterT, writerT, runWriterT, execWriterT, mapWriterT)
Control/Monad/Writer/Class.hs view
@@ -1,3 +1,7 @@+{-# LANGUAGE Safe #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-} -- Search for UndecidableInstances to see why this is needed @@ -26,25 +30,25 @@ censor, ) where -import Control.Monad.Trans.Error as Error-import Control.Monad.Trans.Except as Except-import Control.Monad.Trans.Identity as Identity-import Control.Monad.Trans.Maybe as Maybe-import Control.Monad.Trans.Reader-import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS (- RWST, writer, tell, listen, pass)-import qualified Control.Monad.Trans.RWS.Strict as StrictRWS (- RWST, writer, tell, listen, pass)-import Control.Monad.Trans.State.Lazy as Lazy-import Control.Monad.Trans.State.Strict as Strict-import qualified Control.Monad.Trans.Writer.Lazy as Lazy (- WriterT, writer, tell, listen, pass)-import qualified Control.Monad.Trans.Writer.Strict as Strict (- WriterT, writer, tell, listen, pass)-+import Control.Monad.Trans.Except (ExceptT)+import qualified Control.Monad.Trans.Except as Except+import Control.Monad.Trans.Identity (IdentityT)+import qualified Control.Monad.Trans.Identity as Identity+import Control.Monad.Trans.Maybe (MaybeT)+import qualified Control.Monad.Trans.Maybe as Maybe+import Control.Monad.Trans.Reader (ReaderT, mapReaderT)+import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS +import qualified Control.Monad.Trans.RWS.Strict as StrictRWS +import qualified Control.Monad.Trans.State.Lazy as Lazy+import qualified Control.Monad.Trans.State.Strict as Strict+import qualified Control.Monad.Trans.Writer.Lazy as Lazy+import qualified Control.Monad.Trans.Writer.Strict as Strict +import Control.Monad.Trans.Accum (AccumT)+import qualified Control.Monad.Trans.Accum as Accum+import qualified Control.Monad.Trans.RWS.CPS as CPSRWS+import qualified Control.Monad.Trans.Writer.CPS as CPS import Control.Monad.Trans.Class (lift)-import Control.Monad-import Data.Monoid+import Data.Functor.Product (Product(..)) -- --------------------------------------------------------------------------- -- MonadWriter class@@ -59,6 +63,7 @@ -- the written object. class (Monoid w, Monad m) => MonadWriter w m | m -> w where+ {-# MINIMAL (writer | tell), listen, pass #-} -- | @'writer' (a,w)@ embeds a simple writer action. writer :: (a,w) -> m a writer ~(a, w) = do@@ -96,6 +101,20 @@ a <- m return (a, f) +-- | @since 2.2.2+instance (Monoid w) => MonadWriter w ((,) w) where+ writer ~(a, w) = (w, a)+ tell w = (w, ())+ listen ~(w, a) = (w, (a, w))+ pass ~(w, (a, f)) = (f w, a)++-- | @since 2.3+instance (Monoid w, Monad m) => MonadWriter w (CPS.WriterT w m) where+ writer = CPS.writer+ tell = CPS.tell+ listen = CPS.listen+ pass = CPS.pass+ instance (Monoid w, Monad m) => MonadWriter w (Lazy.WriterT w m) where writer = Lazy.writer tell = Lazy.tell@@ -108,6 +127,13 @@ listen = Strict.listen pass = Strict.pass +-- | @since 2.3+instance (Monoid w, Monad m) => MonadWriter w (CPSRWS.RWST r w s m) where+ writer = CPSRWS.writer+ tell = CPSRWS.tell+ listen = CPSRWS.listen+ pass = CPSRWS.pass+ instance (Monoid w, Monad m) => MonadWriter w (LazyRWS.RWST r w s m) where writer = LazyRWS.writer tell = LazyRWS.tell@@ -126,12 +152,7 @@ -- All of these instances need UndecidableInstances, -- because they do not satisfy the coverage condition. -instance (Error e, MonadWriter w m) => MonadWriter w (ErrorT e m) where- writer = lift . writer- tell = lift . tell- listen = Error.liftListen listen- pass = Error.liftPass pass-+-- | @since 2.2 instance MonadWriter w m => MonadWriter w (ExceptT e m) where writer = lift . writer tell = lift . tell@@ -167,3 +188,28 @@ tell = lift . tell listen = Strict.liftListen listen pass = Strict.liftPass pass++-- | There are two valid instances for 'AccumT'. It could either:+--+-- 1. Lift the operations to the inner @MonadWriter@+-- 2. Handle the operations itself, à la a @WriterT@.+--+-- This instance chooses (1), reflecting that the intent+-- of 'AccumT' as a type is different than that of @WriterT@.+--+-- @since 2.3+instance+ ( Monoid w'+ , MonadWriter w m+ ) => MonadWriter w (AccumT w' m) where+ writer = lift . writer+ tell = lift . tell+ listen = Accum.liftListen listen+ pass = Accum.liftPass pass++-- | @since 2.3.2+instance (MonadWriter w m, MonadWriter w n) => MonadWriter w (Product m n) where+ writer aw = Pair (writer aw) (writer aw)+ tell w = Pair (tell w) (tell w)+ listen (Pair ma na) = Pair (listen ma) (listen na)+ pass (Pair maf naf) = Pair (pass maf) (pass naf)
Control/Monad/Writer/Lazy.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.Writer.Lazy@@ -19,31 +20,24 @@ module Control.Monad.Writer.Lazy ( -- * MonadWriter class- MonadWriter(..),- listens,- censor,+ MonadWriter.MonadWriter(..),+ MonadWriter.listens,+ MonadWriter.censor, -- * The Writer monad Writer, runWriter, execWriter, mapWriter, -- * The WriterT monad transformer- WriterT(..),+ WriterT(WriterT),+ runWriterT, execWriterT, mapWriterT,- module Control.Monad,- module Control.Monad.Fix, module Control.Monad.Trans,- module Data.Monoid, ) where -import Control.Monad.Writer.Class-+import qualified Control.Monad.Writer.Class as MonadWriter import Control.Monad.Trans import Control.Monad.Trans.Writer.Lazy ( Writer, runWriter, execWriter, mapWriter,- WriterT(..), execWriterT, mapWriterT)--import Control.Monad-import Control.Monad.Fix-import Data.Monoid+ WriterT(WriterT), runWriterT, execWriterT, mapWriterT)
Control/Monad/Writer/Strict.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.Writer.Strict@@ -19,9 +20,9 @@ module Control.Monad.Writer.Strict ( -- * MonadWriter class- MonadWriter(..),- listens,- censor,+ MonadWriter.MonadWriter(..),+ MonadWriter.listens,+ MonadWriter.censor, -- * The Writer monad Writer, runWriter,@@ -31,19 +32,11 @@ WriterT(..), execWriterT, mapWriterT,- module Control.Monad,- module Control.Monad.Fix, module Control.Monad.Trans,- module Data.Monoid, ) where -import Control.Monad.Writer.Class-+import qualified Control.Monad.Writer.Class as MonadWriter import Control.Monad.Trans import Control.Monad.Trans.Writer.Strict ( Writer, runWriter, execWriter, mapWriter, WriterT(..), execWriterT, mapWriterT)--import Control.Monad-import Control.Monad.Fix-import Data.Monoid
+ README.markdown view
@@ -0,0 +1,164 @@+# `mtl` [](https://hackage.haskell.org/package/mtl)++MTL is a collection of monad classes, extending the `transformers`+package, using functional dependencies for generic lifting of monadic+actions.++## Structure++Transformers in MTL are divided into classes and data types. Classes+define the monadic operations of transformers. Data types, generally+from the `transformers` package, implement transformers, and MTL+provides instances for all the transformer type classes.++MTL and `transformers` use a common module, data type, and function+naming scheme. As an example, let's imagine we have a transformer+`Foo`.++In the `Control.Monad.Foo` module, we'd find:++* A type class `MonadFoo` with the transformer operations.+* A data type `FooT` with instances for all monad transformer classes.+* Functions to run the transformed computation, e.g. `runFooT`. For+ the actual transformers, there are usually a number of useful runner+ functions.++### Lifting++When using monad transformers, you often need to "lift" a monadic+action into your transformed monadic action. This is done using the+`lift` function from `MonadTrans` in the `Control.Monad.Trans.Class`+module:++``` haskell+lift :: (Monad m, MonadTrans t) => m a -> t m a+```++The action `m a` is lifted into the transformer action `t m a`.++As an example, here we lift an action of type `IO a` into an action of+type `ExceptT MyError IO a`:++``` haskell+data MyError = EmptyLine++mightFail :: ExceptT MyError IO ()+mightFail = do+ l <- lift getLine+ when (null l) (throwError EmptyLine)+```++### Transformers++The following outlines the available monad classes and transformers in+MTL and `transformers`. For more details, and the corresponding+documentation of the `mtl` version you are using, see [the+documentation on Hackage](https://hackage.haskell.org/package/mtl).++* `Control.Monad.Cont`++ The Continuation monad transformer adds the ability to use+ [continuation-passing style+ (CPS)](https://en.wikipedia.org/wiki/Continuation-passing_style)+ in a monadic computation. Continuations can be used to manipulate+ the control flow of a program, e.g. early exit, error handling, or+ suspending a computation.++ - Class: `Control.Monad.Cont.Class.MonadCont`+ - Transformer: `Control.Monad.Cont.ContT`++* `Control.Monad.Error` (deprecated!)++ The Error monad transformer has been deprecated in favor of+ `Control.Monad.Except`.++* `Control.Monad.Except`++ The Except monad transformer adds the ability to fail with an+ error in a monadic computation.++ - Class: `Control.Monad.Except.Class.MonadError`+ - Transformer: `Control.Monad.Except.ExceptT`++* `Control.Monad.Identity`++ The Identity monad transformer does not add any abilities to a+ monad. It simply applies the bound function to its inner monad+ without any modification.++ - Transformer: `Control.Monad.Trans.Identity.IdentityT` (in the `transformers` package)+ - Identity functor and monad: `Data.Functor.Identity.Identity` (in the `base` package)++* `Control.Monad.RWS`++ A convenient transformer that combines the Reader, Writer, and+ State monad transformers.++ - Lazy transformer: `Control.Monad.RWS.Lazy.RWST` (which is the default, exported by `Control.Monad.RWS`)+ - Strict transformer: `Control.Monad.RWS.Strict.RWST`++* `Control.Monad.Reader`++ The Reader monad transformer represents a computation which can+ read values from an environment.++ - Class: `Control.Monad.Reader.Class.MonadReader`+ - Transformer: `Control.Monad.Reader.ReaderT`++* `Control.Monad.State`++ The State monad transformer represents a computation which can+ read and write internal state values. If you only need to _read_+ values, you might want to use+ [Reader](http://hackage.haskell.org/package/mtl/docs/Control-Monad-Reader.html)+ instead.++ - Class: `Control.Monad.State.Class.MonadState`+ - Lazy transformer: `Control.Monad.State.Lazy.StateT` (the default, exported by `Control.Monad.State`)+ - Strict transformer: `Control.Monad.State.Strict.StateT`++* `Control.Monad.Writer`++ The Writer monad transformer represents a computation that can+ produce a stream of data in addition to the computed values. This+ can be used to collect values in some data structure with a+ `Monoid` instance. This can be used for things like logging and+ accumulating values throughout a computation.++ - Class: `Control.Monad.Writer.Class.MonadWriter`+ - Lazy transformers: `Control.Monad.Writer.Lazy.WriterT`+ - Strict transformers: `Control.Monad.Writer.Strict.WriterT`++* `Control.Monad.Accum`++ The `Accum` monad transformer represents a computation which+ manages append-only state, or a writer that can read all+ previous inputs. It binds a function to a monadic value by+ lazily accumulating subcomputations via `(<>)`. For more general+ access, use [State](https://hackage.haskell.org/package/transformers-0.6.0.4/docs/Control-Monad-Trans-State.html) instead.++ - Class: `Control.Monad.Accum`+ - Transformer: `Control.Monad.Trans.Accum.AccumT`++* `Control.Monad.Select`++ The `Select` monad transformer represents a computation which+ can do backtracking search using a 'ranked' evaluation strategy.+ Binding a function to a monad value chains together evaluation+ strategies in the sense that the results of previous strategies+ may influence subsequent rank and evaluation strategies in+ subcomputations.++ - Class: `Control.Monad.Select`+ - Transformer: `Control.Monad.Trans.Select.SelectT`++## Resources++* [`mtl` on Hackage](http://hackage.haskell.org/package/mtl)+* The [Monad Transformers](http://dev.stephendiehl.com/hask/#monad-transformers)+ chapter in "What I Wish I Knew When Learning Haskell".+* References:+ - This package is inspired by the paper _Functional Programming+ with Overloading and Higher-Order Polymorphism_, by Mark P+ Jones, in _Advanced School of Functional Programming_, 1995+ (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>).
mtl.cabal view
@@ -1,37 +1,44 @@-name: mtl-version: 2.2-cabal-version: >= 1.6-license: BSD3-license-file: LICENSE-author: Andy Gill-maintainer: Edward Kmett <ekmett@gmail.com>-category: Control-synopsis: Monad classes, using functional dependencies-homepage: http://github.com/ekmett/mtl-bug-reports: http://github.com/ekmett/mtl/issues+cabal-version: 3.0+name: mtl+version: 2.3.2+license: BSD-3-Clause+license-file: LICENSE+author: Andy Gill+maintainer: Koz Ross <koz.ross@retro-freedom.nz>+ Steven Shuck <stevenjshuck@gmail.com>+category: Control+synopsis: Monad classes for transformers, using functional dependencies+homepage: http://github.com/haskell/mtl+bug-reports: http://github.com/haskell/mtl/issues description:- Monad classes using functional dependencies, with instances- for various monad transformers, inspired by the paper- /Functional Programming with Overloading and Higher-Order Polymorphism/,- by Mark P Jones, in /Advanced School of Functional Programming/, 1995- (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>).+ MTL is a collection of monad classes, extending the 'transformers'+ package, using functional dependencies for generic lifting of+ monadic actions.+ build-type: Simple-extra-source-files: CHANGELOG.markdown +extra-source-files:+ README.markdown++extra-doc-files:+ CHANGELOG.markdown++tested-with: GHC ==8.10 || ==9.2 || ==9.8 || ==9.10 || ==9.12, MHS ==0.14.15.0+ source-repository head type: git- location: git://github.com/ekmett/mtl.git+ location: https://github.com/haskell/mtl.git Library exposed-modules: Control.Monad.Cont Control.Monad.Cont.Class- Control.Monad.Error Control.Monad.Error.Class+ Control.Monad.Except Control.Monad.Identity- Control.Monad.List Control.Monad.RWS Control.Monad.RWS.Class+ Control.Monad.RWS.CPS Control.Monad.RWS.Lazy Control.Monad.RWS.Strict Control.Monad.Reader@@ -43,11 +50,19 @@ Control.Monad.Trans Control.Monad.Writer Control.Monad.Writer.Class+ Control.Monad.Writer.CPS Control.Monad.Writer.Lazy Control.Monad.Writer.Strict- build-depends: base < 6, transformers == 0.4.*- extensions:- MultiParamTypeClasses- FunctionalDependencies- FlexibleInstances- ghc-options: -Wall -fno-warn-unused-imports+ Control.Monad.Accum+ Control.Monad.Select++ build-depends:+ , base >=4.12 && < 5+ , transformers >= 0.5.6 && <0.7++ ghc-options:+ -Wall -Wcompat -Wincomplete-record-updates+ -Wincomplete-uni-patterns -Wredundant-constraints+ -Wmissing-export-lists++ default-language: Haskell2010