packages feed

mtl 1.1.1.1 → 2.3.2

raw patch · 30 files changed

Files

+ CHANGELOG.markdown view
@@ -0,0 +1,75 @@+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 -- 2014-03-24+-------+* Avoid importing `Control.Monad.Instances` on GHC 7.8 to build without deprecation warnings.++2.1.3+-----+* Removed the now-irrelevant `Error` constraint from the `MonadError` instance for `Either e`.
+ 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,16 +1,15 @@-{-# LANGUAGE UndecidableInstances #-}--- Search for UndecidableInstances to see why this is needed+{-# LANGUAGE Safe #-}  {- | Module      :  Control.Monad.Cont Copyright   :  (c) The University of Glasgow 2001,                (c) Jeff Newbern 2003-2007,                (c) Andriy Palamarchuk 2007-License     :  BSD-style (see the file libraries/base/LICENSE)+License     :  BSD-style (see the file LICENSE)  Maintainer  :  libraries@haskell.org Stability   :  experimental-Portability :  non-portable (multi-parameter type classes)+Portability :  portable  [Computation type:] Computations which can be interrupted and resumed. @@ -52,111 +51,39 @@ -}  module Control.Monad.Cont (-    module Control.Monad.Cont.Class,-    Cont(..),-    mapCont,-    withCont,-    ContT(..),-    mapContT,-    withContT,-    module Control.Monad,-    module Control.Monad.Trans,+    -- * MonadCont class+    MonadCont.MonadCont(..),+    MonadCont.label,+    MonadCont.label_,++    -- * The Cont monad+    Cont.Cont,+    Cont.cont,+    Cont.runCont,+    Cont.evalCont,+    Cont.mapCont,+    Cont.withCont,+    -- * The ContT monad transformer+    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-import Control.Monad.Cont.Class-import Control.Monad.Reader.Class-import Control.Monad.State.Class-import Control.Monad.Trans--{- |-Continuation monad.-@Cont r a@ is a CPS computation that produces an intermediate result-of type @a@ within a CPS computation whose final result type is @r@.--The @return@ function simply creates a continuation which passes the value on.--The @>>=@ operator adds the bound function into the continuation chain.--}-newtype Cont r a = Cont {--    {- | Runs a CPS computation, returns its result after applying-    the final continuation to it.-    Parameters:--    * a continuation computation (@Cont@).--    * the final continuation, which produces the final result (often @id@).-    -}-    runCont :: (a -> r) -> r-}--mapCont :: (r -> r) -> Cont r a -> Cont r a-mapCont f m = Cont $ f . runCont m--withCont :: ((b -> r) -> (a -> r)) -> Cont r a -> Cont r b-withCont f m = Cont $ runCont m . f--instance Functor (Cont r) where-    fmap f m = Cont $ \c -> runCont m (c . f)--instance Monad (Cont r) where-    return a = Cont ($ a)-    m >>= k  = Cont $ \c -> runCont m $ \a -> runCont (k a) c--instance MonadCont (Cont r) where-    callCC f = Cont $ \c -> runCont (f (\a -> Cont $ \_ -> c a)) c--{- |-The continuation monad transformer.-Can be used to add continuation handling to other monads.--}-newtype ContT r m a = ContT { runContT :: (a -> m r) -> m r }--mapContT :: (m r -> m r) -> ContT r m a -> ContT r m a-mapContT f m = ContT $ f . runContT m--withContT :: ((b -> m r) -> (a -> m r)) -> ContT r m a -> ContT r m b-withContT f m = ContT $ runContT m . f--instance (Monad m) => Functor (ContT r m) where-    fmap f m = ContT $ \c -> runContT m (c . f)--instance (Monad m) => Monad (ContT r m) where-    return a = ContT ($ a)-    m >>= k  = ContT $ \c -> runContT m (\a -> runContT (k a) c)--instance (Monad m) => MonadCont (ContT r m) where-    callCC f = ContT $ \c -> runContT (f (\a -> ContT $ \_ -> c a)) c---- ------------------------------------------------------------------------------ Instances for other mtl transformers--instance MonadTrans (ContT r) where-    lift m = ContT (m >>=)--instance (MonadIO m) => MonadIO (ContT r m) where-    liftIO = lift . liftIO---- Needs UndecidableInstances-instance (MonadReader r' m) => MonadReader r' (ContT r m) where-    ask       = lift ask-    local f m = ContT $ \c -> do-        r <- ask-        local f (runContT m (local (const r) . c))+    -- * Example 4: Using @label@+    -- $labelExample+  ) where --- Needs UndecidableInstances-instance (MonadState s m) => MonadState s (ContT r m) where-    get = lift get-    put = lift . put+import qualified Control.Monad.Cont.Class as MonadCont+import qualified Control.Monad.Trans.Cont as Cont  {- $simpleContExample Calculating length of a list continuation-style:@@ -203,15 +130,15 @@ (1) Runs an anonymous 'Cont' block and extracts value from it with @(\`runCont\` id)@. Here @id@ is the continuation, passed to the @Cont@ block. -(1) Binds @response@ to the result of the following 'callCC' block,+(1) Binds @response@ to the result of the following 'Control.Monad.Cont.Class.callCC' block, binds @exit@ to the continuation.  (1) Validates @name@.-This approach illustrates advantage of using 'callCC' over @return@.+This approach illustrates advantage of using 'Control.Monad.Cont.Class.callCC' over @return@. We pass the continuation to @validateName@, and interrupt execution of the @Cont@ block from /inside/ of @validateName@. -(1) Returns the welcome message from the @callCC@ block.+(1) Returns the welcome message from the 'Control.Monad.Cont.Class.callCC' block. This line is not executed if @validateName@ fails.  (1) Returns from the @Cont@ block.@@ -243,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,16 +1,23 @@-{-# LANGUAGE UndecidableInstances #-}--- Search for UndecidableInstances to see why this is needed+{-# 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,                (c) Jeff Newbern 2003-2007,                (c) Andriy Palamarchuk 2007-License     :  BSD-style (see the file libraries/base/LICENSE)+License     :  BSD-style (see the file LICENSE)  Maintainer  :  libraries@haskell.org Stability   :  experimental-Portability :  non-portable (multi-parameter type classes)+Portability :  portable  [Computation type:] Computations which can be interrupted and resumed. @@ -53,17 +60,46 @@  module Control.Monad.Cont.Class (     MonadCont(..),+    label,+    label_,+    liftCallCC,   ) where -class (Monad m) => MonadCont m 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.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 :: 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@@ -75,4 +111,110 @@     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++-- | @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 (MaybeT m) where+    callCC = Maybe.liftCallCC callCC++instance MonadCont m => MonadCont (ReaderT r m) where+    callCC = Reader.liftCallCC callCC++instance (Monoid w, MonadCont m) => MonadCont (LazyRWS.RWST r w s m) where+    callCC = LazyRWS.liftCallCC' callCC++instance (Monoid w, MonadCont m) => MonadCont (StrictRWS.RWST r w s m) where+    callCC = StrictRWS.liftCallCC' callCC++instance MonadCont m => MonadCont (LazyState.StateT s m) where+    callCC = LazyState.liftCallCC' callCC++instance MonadCont m => MonadCont (StrictState.StateT s m) where+    callCC = StrictState.liftCallCC' callCC++instance (Monoid w, MonadCont m) => MonadCont (LazyWriter.WriterT w m) where+    callCC = LazyWriter.liftCallCC callCC++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,304 +0,0 @@--- Undecidable instances needed for the same reasons as in Reader, State etc:-{-# LANGUAGE UndecidableInstances #-}--- De-orphaning this module is tricky:-{-# OPTIONS_GHC -fno-warn-orphans #-}--- To handle instances moved to base:-{-# 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 libraries/base/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://www.cse.ogi.edu/~andy/>)--}-module Control.Monad.Error (-    module Control.Monad.Error.Class,-    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-import Control.Monad.Cont.Class-import Control.Monad.Error.Class-import Control.Monad.Fix-import Control.Monad.Reader.Class-import Control.Monad.State.Class-import Control.Monad.Trans-import Control.Monad.Writer.Class-import Control.Monad.RWS.Class--import Control.Monad.Instances ()---- | Note: this instance does not satisfy the second 'MonadPlus' law------ > v >> mzero   =  mzero----instance MonadPlus IO where-    mzero       = ioError (userError "mzero")-    m `mplus` n = m `catch` \_ -> n--instance MonadError IOError IO where-    throwError = ioError-    catchError = catch---- ------------------------------------------------------------------------------ Our parameterizable error monad--#if !(MIN_VERSION_base(4,2,1))---- These instances are in base-4.3, minus the fail definition and--- the Error constraint--instance (Error e) => Monad (Either e) where-    return        = Right-    Left  l >>= _ = Left l-    Right r >>= k = k r-    fail msg      = Left (strMsg msg)--instance (Error e) => MonadFix (Either e) where-    mfix f = let-        a = f $ case a of-            Right r -> r-            _       -> error "empty mfix argument"-        in a--#endif /* base to 4.2.0.x */--instance (Error e) => MonadPlus (Either e) where-    mzero            = Left noMsg-    Left _ `mplus` n = n-    m      `mplus` _ = m--instance (Error e) => MonadError e (Either e) where-    throwError             = Left-    Left  l `catchError` h = h l-    Right r `catchError` _ = Right r--{- |-The error monad transformer. It can be used to add error handling to other-monads.--The @ErrorT@ Monad structure is parameterized over two things:-- * e - The error type.-- * m - The inner monad.--Here are some examples of use:--> -- wraps IO action that can throw an error e-> type ErrorWithIO e a = ErrorT e IO a-> ==> ErrorT (IO (Either e a))->-> -- IO monad wrapped in StateT inside of ErrorT-> type ErrorAndStateWithIO e s a = ErrorT e (StateT s IO) a-> ==> ErrorT (StateT s IO (Either e a))-> ==> ErrorT (StateT (s -> IO (Either e a,s)))--}--newtype ErrorT e m a = ErrorT { runErrorT :: m (Either e a) }--mapErrorT :: (m (Either e a) -> n (Either e' b))-          -> ErrorT e m a-          -> ErrorT e' n b-mapErrorT f m = ErrorT $ f (runErrorT m)--instance (Monad m) => Functor (ErrorT e m) where-    fmap f m = ErrorT $ do-        a <- runErrorT m-        case a of-            Left  l -> return (Left  l)-            Right r -> return (Right (f r))--instance (Monad m, Error e) => Monad (ErrorT e m) where-    return a = ErrorT $ return (Right a)-    m >>= k  = ErrorT $ do-        a <- runErrorT m-        case a of-            Left  l -> return (Left l)-            Right r -> runErrorT (k r)-    fail msg = ErrorT $ return (Left (strMsg msg))--instance (Monad m, Error e) => MonadPlus (ErrorT e m) where-    mzero       = ErrorT $ return (Left noMsg)-    m `mplus` n = ErrorT $ do-        a <- runErrorT m-        case a of-            Left  _ -> runErrorT n-            Right r -> return (Right r)--instance (MonadFix m, Error e) => MonadFix (ErrorT e m) where-    mfix f = ErrorT $ mfix $ \a -> runErrorT $ f $ case a of-        Right r -> r-        _       -> error "empty mfix argument"--instance (Monad m, Error e) => MonadError e (ErrorT e m) where-    throwError l     = ErrorT $ return (Left l)-    m `catchError` h = ErrorT $ do-        a <- runErrorT m-        case a of-            Left  l -> runErrorT (h l)-            Right r -> return (Right r)---- ------------------------------------------------------------------------------ Instances for other mtl transformers--instance (Error e) => MonadTrans (ErrorT e) where-    lift m = ErrorT $ do-        a <- m-        return (Right a)--instance (Error e, MonadIO m) => MonadIO (ErrorT e m) where-    liftIO = lift . liftIO--instance (Error e, MonadCont m) => MonadCont (ErrorT e m) where-    callCC f = ErrorT $-        callCC $ \c ->-        runErrorT (f (\a -> ErrorT $ c (Right a)))--instance (Error e, MonadRWS r w s m) => MonadRWS r w s (ErrorT e m)--instance (Error e, MonadReader r m) => MonadReader r (ErrorT e m) where-    ask       = lift ask-    local f m = ErrorT $ local f (runErrorT m)--instance (Error e, MonadState s m) => MonadState s (ErrorT e m) where-    get = lift get-    put = lift . put--instance (Error e, MonadWriter w m) => MonadWriter w (ErrorT e m) where-    tell     = lift . tell-    listen m = ErrorT $ do-        (a, w) <- listen (runErrorT m)-        case a of-            Left  l -> return $ Left  l-            Right r -> return $ Right (r, w)-    pass   m = ErrorT $ pass $ do-        a <- runErrorT m-        case a of-            Left  l      -> return (Left  l, id)-            Right (r, f) -> return (Right r, f)--{- $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,12 +1,20 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-}--- Needed for the same reasons as in Reader, State etc+{-# 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 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 libraries/base/LICENSE)+               (c) Edward Kmett 2012+License     :  BSD-style (see the file LICENSE)  Maintainer  :  libraries@haskell.org Stability   :  experimental@@ -24,7 +32,7 @@ [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@+[Example type:] @'Either' 'String' a@  The Error monad (also called the Exception monad). -}@@ -32,33 +40,43 @@ {-   Rendered by Michael Weber <mailto:michael.weber@post.rwth-aachen.de>,   inspired by the Haskell Monad Template Library from-    Andy Gill (<http://www.cse.ogi.edu/~andy/>)+    Andy Gill (<http://web.cecs.pdx.edu/~andy/>) -} module Control.Monad.Error.Class (-    Error(..),     MonadError(..),+    liftEither,+    tryError,+    withError,+    handleError,+    onError,+    mapError,+    modifyError,   ) where --- | An exception to be thrown.--- An instance must redefine at least one of 'noMsg', 'strMsg'.-class Error a where-    -- | Creates an exception without a message.-    -- Default implementation is @'strMsg' \"\"@.-    noMsg  :: a-    -- | Creates an exception with a message.-    -- Default implementation is 'noMsg'.-    strMsg :: String -> a--    noMsg    = strMsg ""-    strMsg _ = noMsg---- | A string can be thrown as an error.-instance Error String where-    noMsg  = ""-    strMsg = id--instance Error IOError where-    strMsg = userError+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 (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@@ -67,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 @'Data.Either' String@ or @'Data.Either' IOError@.-In these cases you will have to explicitly define instances of the 'Error'-and\/or 'MonadError' classes.+other than @'Either' 'String'@ or @'Either' 'IOError'@.+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.@@ -90,4 +110,186 @@     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++instance MonadError e (Either e) where+    throwError             = Left+    Left  l `catchError` h = h l+    Right r `catchError` _ = Right r++{- | @since 2.2 -}+instance Monad m => MonadError e (ExceptT e m) where+    throwError = ExceptT.throwE+    catchError = ExceptT.catchE++-- ---------------------------------------------------------------------------+-- Instances for other mtl transformers+--+-- All of these instances need UndecidableInstances,+-- because they do not satisfy the coverage condition.++instance MonadError e m => MonadError e (IdentityT m) where+    throwError = lift . throwError+    catchError = Identity.liftCatch catchError++instance MonadError e m => MonadError e (MaybeT m) where+    throwError = lift . throwError+    catchError = Maybe.liftCatch catchError++instance MonadError e m => MonadError e (ReaderT r m) where+    throwError = lift . throwError+    catchError = Reader.liftCatch catchError++instance (Monoid w, MonadError e m) => MonadError e (LazyRWS.RWST r w s m) where+    throwError = lift . throwError+    catchError = LazyRWS.liftCatch catchError++instance (Monoid w, MonadError e m) => MonadError e (StrictRWS.RWST r w s m) where+    throwError = lift . throwError+    catchError = StrictRWS.liftCatch catchError++instance MonadError e m => MonadError e (LazyState.StateT s m) where+    throwError = lift . throwError+    catchError = LazyState.liftCatch catchError++instance MonadError e m => MonadError e (StrictState.StateT s m) where+    throwError = lift . throwError+    catchError = StrictState.liftCatch catchError++instance (Monoid w, MonadError e m) => MonadError e (LazyWriter.WriterT w m) where+    throwError = lift . throwError+    catchError = LazyWriter.liftCatch catchError++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,10 +1,11 @@+{-# LANGUAGE Safe #-} {- | Module      :  Control.Monad.Identity Copyright   :  (c) Andy Gill 2001,                (c) Oregon Graduate Institute of Science and Technology 2001,                (c) Jeff Newbern 2003-2006,                (c) Andriy Palamarchuk 2006-License     :  BSD-style (see the file libraries/base/LICENSE)+License     :  BSD-style (see the file LICENSE)  Maintainer  :  libraries@haskell.org Stability   :  experimental@@ -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.@@ -30,66 +31,12 @@ of monad transformers. Any monad transformer applied to the @Identity@ monad yields a non-transformer version of that monad.--  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. -}  module Control.Monad.Identity (-    Identity(..),--    module Control.Monad,-    module Control.Monad.Fix,+    module Data.Functor.Identity,+    module Control.Monad.Trans.Identity,    ) where -import Control.Monad-import Control.Monad.Fix--{- | Identity wrapper.-Abstraction for wrapping up a object.-If you have an monadic function, say:-->   example :: Int -> Identity Int->   example x = return (x*x)--     you can \"run\" it, using--> Main> runIdentity (example 42)-> 1764 :: Int--A typical use of the Identity monad is to derive a monad-from a monad transformer.--@--- derive the 'Control.Monad.State.State' monad using the 'Control.Monad.State.StateT' monad transformer-type 'Control.Monad.State.State' s a = 'Control.Monad.State.StateT' s 'Identity' a-@--The @'runIdentity'@ label is used in the type definition because it follows-a style of monad definition that explicitly represents monad values as-computations. In this style, a monadic computation is built up using the monadic-operators and then the value of the computation is extracted-using the @run******@ function.-Because the @Identity@ monad does not do any computation, its definition-is trivial.-For a better example of this style of monad,-see the @'Control.Monad.State.State'@ monad.--}--newtype Identity a = Identity { runIdentity :: a }---- ------------------------------------------------------------------------------ Identity instances for Functor and Monad--instance Functor Identity where-    fmap f m = Identity (f (runIdentity m))--instance Monad Identity where-    return a = Identity a-    m >>= k  = k (runIdentity m)--instance MonadFix Identity where-    mfix f = Identity (fix (runIdentity . f))+import Data.Functor.Identity+import Control.Monad.Trans.Identity
− Control/Monad/List.hs
@@ -1,89 +0,0 @@-{-# LANGUAGE UndecidableInstances #-}--- Needed for the same reasons as in Reader, State etc---------------------------------------------------------------------------------- |--- Module      :  Control.Monad.List--- Copyright   :  (c) Andy Gill 2001,---                (c) Oregon Graduate Institute of Science and Technology, 2001--- License     :  BSD-style (see the file libraries/base/LICENSE)------ Maintainer  :  libraries@haskell.org--- Stability   :  experimental--- Portability :  non-portable (multi-parameter type classes)------ The List monad.-----------------------------------------------------------------------------------module Control.Monad.List (-    ListT(..),-    mapListT,-    module Control.Monad,-    module Control.Monad.Trans,-  ) where--import Control.Monad-import Control.Monad.Cont.Class-import Control.Monad.Error.Class-import Control.Monad.Reader.Class-import Control.Monad.State.Class-import Control.Monad.Trans---- ------------------------------------------------------------------------------ Our parameterizable list monad, with an inner monad--newtype ListT m a = ListT { runListT :: m [a] }--mapListT :: (m [a] -> n [b]) -> ListT m a -> ListT n b-mapListT f m = ListT $ f (runListT m)--instance (Monad m) => Functor (ListT m) where-    fmap f m = ListT $ do-        a <- runListT m-        return (map f a)--instance (Monad m) => Monad (ListT m) where-    return a = ListT $ return [a]-    m >>= k  = ListT $ do-        a <- runListT m-        b <- mapM (runListT . k) a-        return (concat b)-    fail _ = ListT $ return []--instance (Monad m) => MonadPlus (ListT m) where-    mzero       = ListT $ return []-    m `mplus` n = ListT $ do-        a <- runListT m-        b <- runListT n-        return (a ++ b)---- ------------------------------------------------------------------------------ Instances for other mtl transformers--instance MonadTrans ListT where-    lift m = ListT $ do-        a <- m-        return [a]--instance (MonadIO m) => MonadIO (ListT m) where-    liftIO = lift . liftIO--instance (MonadCont m) => MonadCont (ListT m) where-    callCC f = ListT $-        callCC $ \c ->-        runListT (f (\a -> ListT $ c [a]))--instance (MonadError e m) => MonadError e (ListT m) where-    throwError       = lift . throwError-    m `catchError` h = ListT $ runListT m-        `catchError` \e -> runListT (h e)--instance (MonadReader s m) => MonadReader s (ListT m) where-    ask       = lift ask-    local f m = ListT $ local f (runListT m)--instance (MonadState s m) => MonadState s (ListT m) where-    get = lift get-    put = lift . put-
Control/Monad/RWS.hs view
@@ -1,9 +1,11 @@+{-# LANGUAGE Safe #-}+ ----------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.RWS -- Copyright   :  (c) Andy Gill 2001, --                (c) Oregon Graduate Institute of Science and Technology, 2001--- License     :  BSD-style (see the file libraries/base/LICENSE)+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental@@ -12,8 +14,7 @@ -- Declaration of the MonadRWS class. -- --      Inspired by the paper---      /Functional Programming with Overloading and---          Higher-Order Polymorphism/,+--      /Functional Programming with Overloading and Higher-Order Polymorphism/, --        Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>) --          Advanced School of Functional Programming, 1995. -----------------------------------------------------------------------------@@ -21,6 +22,5 @@ module Control.Monad.RWS (     module Control.Monad.RWS.Lazy   ) where-+  import Control.Monad.RWS.Lazy-
+ 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,9 +1,16 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+-- Search for UndecidableInstances to see why this is needed+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE Safe #-}+ ----------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.RWS.Class -- Copyright   :  (c) Andy Gill 2001, --                (c) Oregon Graduate Institute of Science and Technology, 2001--- License     :  BSD-style (see the file libraries/base/LICENSE)+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental@@ -12,8 +19,7 @@ -- Declaration of the MonadRWS class. -- --      Inspired by the paper---      /Functional Programming with Overloading and---          Higher-Order Polymorphism/,+--      /Functional Programming with Overloading and Higher-Order Polymorphism/, --        Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>) --          Advanced School of Functional Programming, 1995. -----------------------------------------------------------------------------@@ -28,8 +34,35 @@ import Control.Monad.Reader.Class import Control.Monad.State.Class import Control.Monad.Writer.Class-import Data.Monoid +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.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 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,10 +1,10 @@-{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.RWS.Lazy -- Copyright   :  (c) Andy Gill 2001, --                (c) Oregon Graduate Institute of Science and Technology, 2001--- License     :  BSD-style (see the file libraries/base/LICENSE)+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental@@ -13,171 +13,35 @@ -- Lazy RWS monad. -- --      Inspired by the paper---      /Functional Programming with Overloading and---          Higher-Order Polymorphism/,+--      /Functional Programming with Overloading and Higher-Order Polymorphism/, --        Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>) --          Advanced School of Functional Programming, 1995. -----------------------------------------------------------------------------  module Control.Monad.RWS.Lazy (-    RWS(..),+    -- * The RWS monad+    RWS,+    rws,+    runRWS,     evalRWS,     execRWS,     mapRWS,     withRWS,-    RWST(..),+    -- * The RWST monad transformer+    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-import Control.Monad.Cont.Class-import Control.Monad.Error.Class-import Control.Monad.Fix-import Control.Monad.Reader.Class-import Control.Monad.State.Class-import Control.Monad.Trans-import Control.Monad.Writer.Class import Control.Monad.RWS.Class-import Data.Monoid -newtype RWS r w s a = RWS { runRWS :: r -> s -> (a, s, w) }--evalRWS :: RWS r w s a -> r -> s -> (a, w)-evalRWS m r s = let-    (a, _, w) = runRWS m r s-    in (a, w)--execRWS :: RWS r w s a -> r -> s -> (s, w)-execRWS m r s = let-    (_, s', w) = runRWS m r s-    in (s', w)--mapRWS :: ((a, s, w) -> (b, s, w')) -> RWS r w s a -> RWS r w' s b-mapRWS f m = RWS $ \r s -> f (runRWS m r s)--withRWS :: (r' -> s -> (r, s)) -> RWS r w s a -> RWS r' w s a-withRWS f m = RWS $ \r s -> uncurry (runRWS m) (f r s)--instance Functor (RWS r w s) where-    fmap f m = RWS $ \r s -> let-        (a, s', w) = runRWS m r s-        in (f a, s', w)--instance (Monoid w) => Monad (RWS r w s) where-    return a = RWS $ \_ s -> (a, s, mempty)-    m >>= k  = RWS $ \r s -> let-        (a, s',  w)  = runRWS m r s-        (b, s'', w') = runRWS (k a) r s'-        in (b, s'', w `mappend` w')--instance (Monoid w) => MonadFix (RWS r w s) where-    mfix f = RWS $ \r s -> let (a, s', w) = runRWS (f a) r s in (a, s', w)--instance (Monoid w) => MonadReader r (RWS r w s) where-    ask       = RWS $ \r s -> (r, s, mempty)-    local f m = RWS $ \r s -> runRWS m (f r) s--instance (Monoid w) => MonadWriter w (RWS r w s) where-    tell   w = RWS $ \_ s -> ((), s, w)-    listen m = RWS $ \r s -> let-        (a, s', w) = runRWS m r s-        in ((a, w), s', w)-    pass   m = RWS $ \r s -> let-        ((a, f), s', w) = runRWS m r s-        in (a, s', f w)--instance (Monoid w) => MonadState s (RWS r w s) where-    get   = RWS $ \_ s -> (s, s, mempty)-    put s = RWS $ \_ _ -> ((), s, mempty)--instance (Monoid w) => MonadRWS r w s (RWS r w s)---- ------------------------------------------------------------------------------ Our parameterizable RWS monad, with an inner monad--newtype RWST r w s m a = RWST { runRWST :: r -> s -> m (a, s, w) }--evalRWST :: (Monad m) => RWST r w s m a -> r -> s -> m (a, w)-evalRWST m r s = do-    ~(a, _, w) <- runRWST m r s-    return (a, w)--execRWST :: (Monad m) => RWST r w s m a -> r -> s -> m (s, w)-execRWST m r s = do-    ~(_, s', w) <- runRWST m r s-    return (s', w)--mapRWST :: (m (a, s, w) -> n (b, s, w')) -> RWST r w s m a -> RWST r w' s n b-mapRWST f m = RWST $ \r s -> f (runRWST m r s)--withRWST :: (r' -> s -> (r, s)) -> RWST r w s m a -> RWST r' w s m a-withRWST f m = RWST $ \r s -> uncurry (runRWST m) (f r s)--instance (Monad m) => Functor (RWST r w s m) where-    fmap f m = RWST $ \r s -> do-        ~(a, s', w) <- runRWST m r s-        return (f a, s', w)--instance (Monoid w, Monad m) => Monad (RWST r w s m) where-    return a = RWST $ \_ s -> return (a, s, mempty)-    m >>= k  = RWST $ \r s -> do-        ~(a, s', w)  <- runRWST m r s-        ~(b, s'',w') <- runRWST (k a) r s'-        return (b, s'', w `mappend` w')-    fail msg = RWST $ \_ _ -> fail msg--instance (Monoid w, MonadPlus m) => MonadPlus (RWST r w s m) where-    mzero       = RWST $ \_ _ -> mzero-    m `mplus` n = RWST $ \r s -> runRWST m r s `mplus` runRWST n r s--instance (Monoid w, MonadFix m) => MonadFix (RWST r w s m) where-    mfix f = RWST $ \r s -> mfix $ \ ~(a, _, _) -> runRWST (f a) r s--instance (Monoid w, Monad m) => MonadReader r (RWST r w s m) where-    ask       = RWST $ \r s -> return (r, s, mempty)-    local f m = RWST $ \r s -> runRWST m (f r) s--instance (Monoid w, Monad m) => MonadWriter w (RWST r w s m) where-    tell   w = RWST $ \_ s -> return ((),s,w)-    listen m = RWST $ \r s -> do-        ~(a, s', w) <- runRWST m r s-        return ((a, w), s', w)-    pass   m = RWST $ \r s -> do-        ~((a, f), s', w) <- runRWST m r s-        return (a, s', f w)--instance (Monoid w, Monad m) => MonadState s (RWST r w s m) where-    get   = RWST $ \_ s -> return (s, s, mempty)-    put s = RWST $ \_ _ -> return ((), s, mempty)--instance (Monoid w, Monad m) => MonadRWS r w s (RWST r w s m)---- ------------------------------------------------------------------------------ Instances for other mtl transformers--instance (Monoid w) => MonadTrans (RWST r w s) where-    lift m = RWST $ \_ s -> do-        a <- m-        return (a, s, mempty)--instance (Monoid w, MonadIO m) => MonadIO (RWST r w s m) where-    liftIO = lift . liftIO--instance (Monoid w, MonadCont m) => MonadCont (RWST r w s m) where-    callCC f = RWST $ \r s ->-        callCC $ \c ->-        runRWST (f (\a -> RWST $ \_ s' -> c (a, s', mempty))) r s--instance (Monoid w, MonadError e m) => MonadError e (RWST r w s m) where-    throwError       = lift . throwError-    m `catchError` h = RWST $ \r s -> runRWST m r s-        `catchError` \e -> runRWST (h e) r s-+import Control.Monad.Trans+import Control.Monad.Trans.RWS.Lazy (+    RWS, rws, runRWS, evalRWS, execRWS, mapRWS, withRWS,+    RWST(RWST), runRWST, evalRWST, execRWST, mapRWST, withRWST)
Control/Monad/RWS/Strict.hs view
@@ -1,179 +1,47 @@-{-# LANGUAGE UndecidableInstances #-}+{-# 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 libraries/base/LICENSE)+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental -- Portability :  non-portable (multi-param classes, functional dependencies) ----- Strict RWS Monad.+-- Strict RWS monad. -- --      Inspired by the paper---      /Functional Programming with Overloading and---          Higher-Order Polymorphism/,+--      /Functional Programming with Overloading and Higher-Order Polymorphism/, --        Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>) --          Advanced School of Functional Programming, 1995. -----------------------------------------------------------------------------  module Control.Monad.RWS.Strict (-    RWS(..),+    -- * The RWS monad+    RWS,+    rws,+    runRWS,     evalRWS,     execRWS,     mapRWS,     withRWS,-    RWST(..),+    -- * The RWST monad transformer+    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-import Control.Monad.Cont.Class-import Control.Monad.Error.Class-import Control.Monad.Fix-import Control.Monad.Reader.Class-import Control.Monad.State.Class-import Control.Monad.Trans-import Control.Monad.Writer.Class import Control.Monad.RWS.Class-import Data.Monoid--newtype RWS r w s a = RWS { runRWS :: r -> s -> (a, s, w) }--evalRWS :: RWS r w s a -> r -> s -> (a, w)-evalRWS m r s = case runRWS m r s of-                    (a, _, w) -> (a, w)--execRWS :: RWS r w s a -> r -> s -> (s, w)-execRWS m r s = case runRWS m r s of-                    (_, s', w) -> (s', w)--mapRWS :: ((a, s, w) -> (b, s, w')) -> RWS r w s a -> RWS r w' s b-mapRWS f m = RWS $ \r s -> f (runRWS m r s)--withRWS :: (r' -> s -> (r, s)) -> RWS r w s a -> RWS r' w s a-withRWS f m = RWS $ \r s -> uncurry (runRWS m) (f r s)--instance Functor (RWS r w s) where-    fmap f m = RWS $ \r s -> case runRWS m r s of-                                 (a, s', w) -> (f a, s', w)--instance (Monoid w) => Monad (RWS r w s) where-    return a = RWS $ \_ s -> (a, s, mempty)-    m >>= k  = RWS $ \r s -> case runRWS m r s of-                                 (a, s',  w) ->-                                     case runRWS (k a) r s' of-                                         (b, s'', w') ->-                                             (b, s'', w `mappend` w')--instance (Monoid w) => MonadFix (RWS r w s) where-    mfix f = RWS $ \r s -> let (a, s', w) = runRWS (f a) r s in (a, s', w)--instance (Monoid w) => MonadReader r (RWS r w s) where-    ask       = RWS $ \r s -> (r, s, mempty)-    local f m = RWS $ \r s -> runRWS m (f r) s--instance (Monoid w) => MonadWriter w (RWS r w s) where-    tell   w = RWS $ \_ s -> ((), s, w)-    listen m = RWS $ \r s -> case runRWS m r s of-                                 (a, s', w) -> ((a, w), s', w)-    pass   m = RWS $ \r s -> case runRWS m r s of-                                 ((a, f), s', w) -> (a, s', f w)--instance (Monoid w) => MonadState s (RWS r w s) where-    get   = RWS $ \_ s -> (s, s, mempty)-    put s = RWS $ \_ _ -> ((), s, mempty)--instance (Monoid w) => MonadRWS r w s (RWS r w s)---- ------------------------------------------------------------------------------ Our parameterizable RWS monad, with an inner monad--newtype RWST r w s m a = RWST { runRWST :: r -> s -> m (a, s, w) }--evalRWST :: (Monad m) => RWST r w s m a -> r -> s -> m (a, w)-evalRWST m r s = do-    (a, _, w) <- runRWST m r s-    return (a, w)--execRWST :: (Monad m) => RWST r w s m a -> r -> s -> m (s, w)-execRWST m r s = do-    (_, s', w) <- runRWST m r s-    return (s', w)--mapRWST :: (m (a, s, w) -> n (b, s, w')) -> RWST r w s m a -> RWST r w' s n b-mapRWST f m = RWST $ \r s -> f (runRWST m r s)--withRWST :: (r' -> s -> (r, s)) -> RWST r w s m a -> RWST r' w s m a-withRWST f m = RWST $ \r s -> uncurry (runRWST m) (f r s)--instance (Monad m) => Functor (RWST r w s m) where-    fmap f m = RWST $ \r s -> do-        (a, s', w) <- runRWST m r s-        return (f a, s', w)--instance (Monoid w, Monad m) => Monad (RWST r w s m) where-    return a = RWST $ \_ s -> return (a, s, mempty)-    m >>= k  = RWST $ \r s -> do-        (a, s', w)  <- runRWST m r s-        (b, s'',w') <- runRWST (k a) r s'-        return (b, s'', w `mappend` w')-    fail msg = RWST $ \_ _ -> fail msg--instance (Monoid w, MonadPlus m) => MonadPlus (RWST r w s m) where-    mzero       = RWST $ \_ _ -> mzero-    m `mplus` n = RWST $ \r s -> runRWST m r s `mplus` runRWST n r s--instance (Monoid w, MonadFix m) => MonadFix (RWST r w s m) where-    mfix f = RWST $ \r s -> mfix $ \ ~(a, _, _) -> runRWST (f a) r s--instance (Monoid w, Monad m) => MonadReader r (RWST r w s m) where-    ask       = RWST $ \r s -> return (r, s, mempty)-    local f m = RWST $ \r s -> runRWST m (f r) s--instance (Monoid w, Monad m) => MonadWriter w (RWST r w s m) where-    tell   w = RWST $ \_ s -> return ((),s,w)-    listen m = RWST $ \r s -> do-        (a, s', w) <- runRWST m r s-        return ((a, w), s', w)-    pass   m = RWST $ \r s -> do-        ((a, f), s', w) <- runRWST m r s-        return (a, s', f w)--instance (Monoid w, Monad m) => MonadState s (RWST r w s m) where-    get   = RWST $ \_ s -> return (s, s, mempty)-    put s = RWST $ \_ _ -> return ((), s, mempty)--instance (Monoid w, Monad m) => MonadRWS r w s (RWST r w s m)---- ------------------------------------------------------------------------------ Instances for other mtl transformers--instance (Monoid w) => MonadTrans (RWST r w s) where-    lift m = RWST $ \_ s -> do-        a <- m-        return (a, s, mempty)--instance (Monoid w, MonadIO m) => MonadIO (RWST r w s m) where-    liftIO = lift . liftIO--instance (Monoid w, MonadCont m) => MonadCont (RWST r w s m) where-    callCC f = RWST $ \r s ->-        callCC $ \c ->-        runRWST (f (\a -> RWST $ \_ s' -> c (a, s', mempty))) r s--instance (Monoid w, MonadError e m) => MonadError e (RWST r w s m) where-    throwError       = lift . throwError-    m `catchError` h = RWST $ \r s -> runRWST m r s-        `catchError` \e -> runRWST (h e) r s+import Control.Monad.Trans +import Control.Monad.Trans.RWS.Strict (+    RWS, rws, runRWS, evalRWS, execRWS, mapRWS, withRWS,+    RWST(RWST), runRWST, evalRWST, execRWST, mapRWST, withRWST)
Control/Monad/Reader.hs view
@@ -1,11 +1,11 @@-{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE Safe #-} {- | Module      :  Control.Monad.Reader Copyright   :  (c) Andy Gill 2001,                (c) Oregon Graduate Institute of Science and Technology 2001,                (c) Jeff Newbern 2003-2007,                (c) Andriy Palamarchuk 2007-License     :  BSD-style (see the file libraries/base/LICENSE)+License     :  BSD-style (see the file LICENSE)  Maintainer  :  libraries@haskell.org Stability   :  experimental@@ -31,22 +31,25 @@ than using the 'Control.Monad.State.State' monad.    Inspired by the paper-  /Functional Programming with Overloading and-      Higher-Order Polymorphism/, +  /Functional Programming with Overloading and Higher-Order Polymorphism/,     Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>)     Advanced School of Functional Programming, 1995. -}  module Control.Monad.Reader (-    module Control.Monad.Reader.Class,-    Reader(..),+    -- * MonadReader class+    MonadReader.MonadReader(..),+    MonadReader.asks,+    -- * The Reader monad+    Reader,+    runReader,     mapReader,     withReader,-    ReaderT(..),+    -- * The ReaderT monad transformer+    ReaderT(ReaderT),+    runReaderT,     mapReaderT,     withReaderT,-    module Control.Monad,-    module Control.Monad.Fix,     module Control.Monad.Trans,     -- * Example 1: Simple Reader Usage     -- $simpleReaderExample@@ -58,137 +61,27 @@     -- $ReaderTExample     ) where -import Control.Monad-import Control.Monad.Cont.Class-import Control.Monad.Error.Class-import Control.Monad.Fix-import Control.Monad.Instances ()-import Control.Monad.Reader.Class-import Control.Monad.State.Class+import qualified Control.Monad.Reader.Class as MonadReader import Control.Monad.Trans-import Control.Monad.Writer.Class -{- |-The parameterizable reader monad.--The @return@ function creates a @Reader@ that ignores the environment,-and produces the given value.--The binding operator @>>=@ produces a @Reader@ that uses the environment-to extract the value its left-hand side,-and then applies the bound function to that value in the same environment.--}-newtype Reader r a = Reader {-    {- |-    Runs @Reader@ and extracts the final value from it.-    To extract the value apply @(runReader reader)@ to an environment value.  -    Parameters:--    * A @Reader@ to run.--    * An initial environment.-    -}-    runReader :: r -> a-}--mapReader :: (a -> b) -> Reader r a -> Reader r b-mapReader f m = Reader $ f . runReader m---- | A more general version of 'local'.--withReader :: (r' -> r) -> Reader r a -> Reader r' a-withReader f m = Reader $ runReader m . f--instance Functor (Reader r) where-    fmap f m = Reader $ \r -> f (runReader m r)--instance Monad (Reader r) where-    return a = Reader $ \_ -> a-    m >>= k  = Reader $ \r -> runReader (k (runReader m r)) r--instance MonadFix (Reader r) where-    mfix f = Reader $ \r -> let a = runReader (f a) r in a--instance MonadReader r (Reader r) where-    ask       = Reader id-    local f m = Reader $ runReader m . f--{- |-The reader monad transformer.-Can be used to add environment reading functionality to other monads.--}-newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }--mapReaderT :: (m a -> n b) -> ReaderT w m a -> ReaderT w n b-mapReaderT f m = ReaderT $ f . runReaderT m--withReaderT :: (r' -> r) -> ReaderT r m a -> ReaderT r' m a-withReaderT f m = ReaderT $ runReaderT m . f--instance (Monad m) => Functor (ReaderT r m) where-    fmap f m = ReaderT $ \r -> do-        a <- runReaderT m r-        return (f a)--instance (Monad m) => Monad (ReaderT r m) where-    return a = ReaderT $ \_ -> return a-    m >>= k  = ReaderT $ \r -> do-        a <- runReaderT m r-        runReaderT (k a) r-    fail msg = ReaderT $ \_ -> fail msg--instance (MonadPlus m) => MonadPlus (ReaderT r m) where-    mzero       = ReaderT $ \_ -> mzero-    m `mplus` n = ReaderT $ \r -> runReaderT m r `mplus` runReaderT n r--instance (MonadFix m) => MonadFix (ReaderT r m) where-    mfix f = ReaderT $ \r -> mfix $ \a -> runReaderT (f a) r--instance (Monad m) => MonadReader r (ReaderT r m) where-    ask       = ReaderT return-    local f m = ReaderT $ \r -> runReaderT m (f r)---- ------------------------------------------------------------------------------ Instances for other mtl transformers--instance MonadTrans (ReaderT r) where-    lift m = ReaderT $ \_ -> m--instance (MonadIO m) => MonadIO (ReaderT r m) where-    liftIO = lift . liftIO--instance (MonadCont m) => MonadCont (ReaderT r m) where-    callCC f = ReaderT $ \r ->-        callCC $ \c ->-        runReaderT (f (\a -> ReaderT $ \_ -> c a)) r--instance (MonadError e m) => MonadError e (ReaderT r m) where-    throwError       = lift . throwError-    m `catchError` h = ReaderT $ \r -> runReaderT m r-        `catchError` \e -> runReaderT (h e) r---- Needs UndecidableInstances-instance (MonadState s m) => MonadState s (ReaderT r m) where-    get = lift get-    put = lift . put---- This instance needs UndecidableInstances, because--- it does not satisfy the coverage condition-instance (MonadWriter w m) => MonadWriter w (ReaderT r m) where-    tell     = lift . tell-    listen m = ReaderT $ \w -> listen (runReaderT m w)-    pass   m = ReaderT $ \w -> pass   (runReaderT m w)+import Control.Monad.Trans.Reader (+    Reader, runReader, mapReader, withReader,+    ReaderT(ReaderT), runReaderT, mapReaderT, withReaderT)  {- $simpleReaderExample  In this example the @Reader@ monad provides access to variable bindings.-Bindings are a 'Map' of integer variables.+Bindings are a @Map@ of integer variables. The variable @count@ contains number of variables in the bindings. You can see how to run a Reader 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@@ -200,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@@ -225,6 +122,7 @@ >calculateModifiedContentLen :: Reader String Int >calculateModifiedContentLen = local ("Prefix " ++) calculateContentLen >+>main :: IO () >main = do >    let s = "12345"; >    let modifiedLen = runReader calculateModifiedContentLen s@@ -237,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,11 +1,20 @@+{-# 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,                (c) Oregon Graduate Institute of Science and Technology 2001,                (c) Jeff Newbern 2003-2007,                (c) Andriy Palamarchuk 2007-License     :  BSD-style (see the file libraries/base/LICENSE)+License     :  BSD-style (see the file LICENSE)  Maintainer  :  libraries@haskell.org Stability   :  experimental@@ -31,8 +40,7 @@ than using the 'Control.Monad.State.State' monad.    Inspired by the paper-  /Functional Programming with Overloading and-      Higher-Order Polymorphism/, +  /Functional Programming with Overloading and Higher-Order Polymorphism/,     Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>)     Advanced School of Functional Programming, 1995. -}@@ -42,25 +50,57 @@     asks,     ) where -import Control.Monad.Instances ()+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+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 Data.Functor.Product (Product(..)) -{- |-See examples in "Control.Monad.Reader".-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+-- ----------------------------------------------------------------------------+-- class MonadReader+--  asks for the internal (non-mutable) state.++-- | See examples in "Control.Monad.Reader".+-- 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-    {- | Executes a computation in a modified environment. Parameters:+    ask = reader id -    * The function to modify the environment.+    -- | Executes a computation in a modified environment.+    local :: (r -> r) -- ^ The function to modify the environment.+          -> m a      -- ^ @Reader@ to run in the modified environment.+          -> m a -    * @Reader@ to run.+    -- | Retrieves a function of the current environment.+    reader :: (r -> a) -- ^ The selector function to apply to the environment.+           -> m a+    reader f = do+      r <- ask+      return (f r) -    * The resulting @Reader@.-    -}-    local :: (r -> r) -> m a -> m a+-- | Retrieves a function of the current environment.+asks :: MonadReader r m+    => (r -> a) -- ^ The selector function to apply to the environment.+    -> m a+asks = reader  -- ---------------------------------------------------------------------------- -- The partially applied function type is a simple reader monad@@ -68,16 +108,103 @@ instance MonadReader r ((->) r) where     ask       = id     local f m = m . f+    reader    = id -{- |-Retrieves a function of the current environment. Parameters:+instance Monad m => MonadReader r (ReaderT r m) where+    ask = ReaderT.ask+    local = ReaderT.local+    reader = ReaderT.reader -* The selector function to apply to the environment.+-- | @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 -See an example in "Control.Monad.Reader".--}-asks :: (MonadReader r m) => (r -> a) -> m a-asks f = do-    r <- ask-    return (f r)+instance (Monad m, Monoid w) => MonadReader r (LazyRWS.RWST r w s m) where+    ask = LazyRWS.ask+    local = LazyRWS.local+    reader = LazyRWS.reader +instance (Monad m, Monoid w) => MonadReader r (StrictRWS.RWST r w s m) where+    ask = StrictRWS.ask+    local = StrictRWS.local+    reader = StrictRWS.reader++-- ---------------------------------------------------------------------------+-- Instances for other mtl transformers+--+-- All of these instances need UndecidableInstances,+-- because they do not satisfy the coverage condition.++instance MonadReader r' m => MonadReader r' (ContT r m) where+    ask   = lift ask+    local = Cont.liftLocal ask local+    reader = lift . reader++{- | @since 2.2 -}+instance MonadReader r m => MonadReader r (ExceptT e m) where+    ask   = lift ask+    local = mapExceptT . local+    reader = lift . reader++instance MonadReader r m => MonadReader r (IdentityT m) where+    ask   = lift ask+    local = mapIdentityT . local+    reader = lift . reader++instance MonadReader r m => MonadReader r (MaybeT m) where+    ask   = lift ask+    local = mapMaybeT . local+    reader = lift . reader++instance MonadReader r m => MonadReader r (Lazy.StateT s m) where+    ask   = lift ask+    local = Lazy.mapStateT . local+    reader = lift . reader++instance MonadReader r m => MonadReader r (Strict.StateT s m) where+    ask   = lift ask+    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+    reader = lift . reader++instance (Monoid w, MonadReader r m) => MonadReader r (Strict.WriterT w m) where+    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,9 +1,10 @@+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.State -- Copyright   :  (c) Andy Gill 2001, --                (c) Oregon Graduate Institute of Science and Technology, 2001--- License     :  BSD-style (see the file libraries/base/LICENSE)+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental@@ -12,8 +13,7 @@ -- State monads. -- --      This module is inspired by the paper---      /Functional Programming with Overloading and---          Higher-Order Polymorphism/,+--      /Functional Programming with Overloading and Higher-Order Polymorphism/, --        Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>) --          Advanced School of Functional Programming, 1995. @@ -24,4 +24,3 @@   ) where  import Control.Monad.State.Lazy-
Control/Monad/State/Class.hs view
@@ -1,9 +1,20 @@+{-# 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 #-}+ ----------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.State.Class -- Copyright   :  (c) Andy Gill 2001, --                (c) Oregon Graduate Institute of Science and Technology, 2001--- License     :  BSD-style (see the file libraries/base/LICENSE)+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental@@ -12,29 +23,58 @@ -- MonadState class. -- --      This module is inspired by the paper---      /Functional Programming with Overloading and---          Higher-Order Polymorphism/,+--      /Functional Programming with Overloading and Higher-Order Polymorphism/, --        Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>) --          Advanced School of Functional Programming, 1995.  -----------------------------------------------------------------------------  module Control.Monad.State.Class (-    -- * MonadState class     MonadState(..),     modify,-    gets,+    modify',+    gets   ) where +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 Data.Functor.Product (Product(..))+ -- ------------------------------------------------------------------------------ | /get/ returns the state from the internals of the monad.------ /put/ replaces the state inside the monad. -class (Monad m) => MonadState s m | m -> s where+-- | Minimal definition is either both of @get@ and @put@ or just @state@+class Monad m => MonadState s m | m -> s where+    -- | Return the state from the internals of the monad.     get :: m s+    get = state (\s -> (s, s))++    -- | Replace the state inside the monad.     put :: s -> m ()+    put s = state (\_ -> ((), s)) +    -- | Embed a simple state action into the monad.+    state :: (s -> (a, s)) -> m a+    state f = do+      s <- get+      let ~(a, s') = f s+      put s'+      return a+    {-# MINIMAL state | get, put #-}+ -- | Monadic state transformer. -- --      Maps an old state to a new state inside a state monad.@@ -46,17 +86,116 @@ --    This says that @modify (+1)@ acts over any --    Monad that is a member of the @MonadState@ class, --    with an @Int@ state.+modify :: MonadState s m => (s -> s) -> m ()+modify f = state (\s -> ((), f s)) -modify :: (MonadState s m) => (s -> s) -> m ()-modify f = do-    s <- get-    put (f s)+-- | 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 = do+  s' <- get+  put $! f s'  -- | Gets specific component of the state, using a projection function -- supplied.--gets :: (MonadState s m) => (s -> a) -> m a+gets :: MonadState s m => (s -> a) -> m a gets f = do     s <- get     return (f s) +instance Monad m => MonadState s (Lazy.StateT s m) where+    get = Lazy.get+    put = Lazy.put+    state = Lazy.state++instance Monad m => MonadState s (Strict.StateT s m) where+    get = Strict.get+    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+    state = LazyRWS.state++instance (Monad m, Monoid w) => MonadState s (StrictRWS.RWST r w s m) where+    get = StrictRWS.get+    put = StrictRWS.put+    state = StrictRWS.state++-- ---------------------------------------------------------------------------+-- Instances for other mtl transformers+--+-- All of these instances need UndecidableInstances,+-- because they do not satisfy the coverage condition.++instance MonadState s m => MonadState s (ContT r 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+    state = lift . state++instance MonadState s m => MonadState s (IdentityT m) where+    get = lift get+    put = lift . put+    state = lift . state++instance MonadState s m => MonadState s (MaybeT m) where+    get = lift get+    put = lift . put+    state = lift . state++instance MonadState s m => MonadState s (ReaderT r m) where+    get = lift get+    put = lift . put+    state = lift . state++-- | @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++instance (Monoid w, MonadState s m) => MonadState s (Lazy.WriterT w m) where+    get = lift get+    put = lift . put+    state = lift . state++instance (Monoid w, MonadState s m) => MonadState s (Strict.WriterT w m) where+    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,12 +1,10 @@-{-# LANGUAGE UndecidableInstances #-}--- Search for UndecidableInstances to see why this is needed-+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.State.Lazy -- Copyright   :  (c) Andy Gill 2001, --                (c) Oregon Graduate Institute of Science and Technology, 2001--- License     :  BSD-style (see the file libraries/base/LICENSE)+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental@@ -15,221 +13,49 @@ -- Lazy state monads. -- --      This module is inspired by the paper---      /Functional Programming with Overloading and---          Higher-Order Polymorphism/,+--      /Functional Programming with Overloading and Higher-Order Polymorphism/, --        Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>) --          Advanced School of Functional Programming, 1995.------ See below for examples.  -----------------------------------------------------------------------------  module Control.Monad.State.Lazy (-    module Control.Monad.State.Class,-    -- * The State Monad-    State(..),+    -- * MonadState class+    MonadState.MonadState(..),+    MonadState.modify,+    MonadState.modify',+    MonadState.gets,+    -- * The State monad+    State,+    runState,     evalState,     execState,     mapState,     withState,-    -- * The StateT Monad-    StateT(..),+    -- * The StateT monad transformer+    StateT(StateT),+    runStateT,     evalStateT,     execStateT,     mapStateT,     withStateT,-    module Control.Monad,-    module Control.Monad.Fix,     module Control.Monad.Trans,     -- * Examples     -- $examples   ) where -import Control.Monad-import Control.Monad.Cont.Class-import Control.Monad.Error.Class-import Control.Monad.Fix-import Control.Monad.Reader.Class-import Control.Monad.State.Class+import qualified Control.Monad.State.Class as MonadState import Control.Monad.Trans-import Control.Monad.Writer.Class --- ------------------------------------------------------------------------------ | A parameterizable state monad where /s/ is the type of the state--- to carry and /a/ is the type of the /return value/.--newtype State s a = State { runState :: s -> (a, s) }---- |Evaluate this state monad with the given initial state,throwing--- away the final state.  Very much like @fst@ composed with--- @runstate@.--evalState :: State s a -- ^The state to evaluate-          -> s         -- ^An initial value-          -> a         -- ^The return value of the state application-evalState m s = fst (runState m s)---- |Execute this state and return the new state, throwing away the--- return value.  Very much like @snd@ composed with--- @runstate@.--execState :: State s a -- ^The state to evaluate-          -> s         -- ^An initial value-          -> s         -- ^The new state-execState m s = snd (runState m s)---- |Map a stateful computation from one (return value, state) pair to--- another.  For instance, to convert numberTree from a function that--- returns a tree to a function that returns the sum of the numbered--- tree (see the Examples section for numberTree and sumTree) you may--- write:------ > sumNumberedTree :: (Eq a) => Tree a -> State (Table a) Int--- > sumNumberedTree = mapState (\ (t, tab) -> (sumTree t, tab))  . numberTree--mapState :: ((a, s) -> (b, s)) -> State s a -> State s b-mapState f m = State $ f . runState m---- |Apply this function to this state and return the resulting state.-withState :: (s -> s) -> State s a -> State s a-withState f m = State $ runState m . f--instance Functor (State s) where-    fmap f m = State $ \s -> let-        (a, s') = runState m s-        in (f a, s')--instance Monad (State s) where-    return a = State $ \s -> (a, s)-    m >>= k  = State $ \s -> let-        (a, s') = runState m s-        in runState (k a) s'--instance MonadFix (State s) where-    mfix f = State $ \s -> let (a, s') = runState (f a) s in (a, s')--instance MonadState s (State s) where-    get   = State $ \s -> (s, s)-    put s = State $ \_ -> ((), s)---- ------------------------------------------------------------------------------ | A parameterizable state monad for encapsulating an inner--- monad.------ The StateT Monad structure is parameterized over two things:------   * s - The state.------   * m - The inner monad.------ Here are some examples of use:------ (Parser from ParseLib with Hugs)------ >  type Parser a = StateT String [] a--- >     ==> StateT (String -> [(a,String)])------ For example, item can be written as:------ >   item = do (x:xs) <- get--- >          put xs--- >          return x--- >--- >   type BoringState s a = StateT s Indentity a--- >        ==> StateT (s -> Identity (a,s))--- >--- >   type StateWithIO s a = StateT s IO a--- >        ==> StateT (s -> IO (a,s))--- >--- >   type StateWithErr s a = StateT s Maybe a--- >        ==> StateT (s -> Maybe (a,s))--newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }---- |Similar to 'evalState'-evalStateT :: (Monad m) => StateT s m a -> s -> m a-evalStateT m s = do-    ~(a, _) <- runStateT m s-    return a---- |Similar to 'execState'-execStateT :: (Monad m) => StateT s m a -> s -> m s-execStateT m s = do-    ~(_, s') <- runStateT m s-    return s'---- |Similar to 'mapState'-mapStateT :: (m (a, s) -> n (b, s)) -> StateT s m a -> StateT s n b-mapStateT f m = StateT $ f . runStateT m---- |Similar to 'withState'-withStateT :: (s -> s) -> StateT s m a -> StateT s m a-withStateT f m = StateT $ runStateT m . f--instance (Monad m) => Functor (StateT s m) where-    fmap f m = StateT $ \s -> do-        ~(x, s') <- runStateT m s-        return (f x, s')--instance (Monad m) => Monad (StateT s m) where-    return a = StateT $ \s -> return (a, s)-    m >>= k  = StateT $ \s -> do-        ~(a, s') <- runStateT m s-        runStateT (k a) s'-    fail str = StateT $ \_ -> fail str--instance (MonadPlus m) => MonadPlus (StateT s m) where-    mzero       = StateT $ \_ -> mzero-    m `mplus` n = StateT $ \s -> runStateT m s `mplus` runStateT n s--instance (MonadFix m) => MonadFix (StateT s m) where-    mfix f = StateT $ \s -> mfix $ \ ~(a, _) -> runStateT (f a) s--instance (Monad m) => MonadState s (StateT s m) where-    get   = StateT $ \s -> return (s, s)-    put s = StateT $ \_ -> return ((), s)---- ------------------------------------------------------------------------------ Instances for other mtl transformers--instance MonadTrans (StateT s) where-    lift m = StateT $ \s -> do-        a <- m-        return (a, s)--instance (MonadIO m) => MonadIO (StateT s m) where-    liftIO = lift . liftIO--instance (MonadCont m) => MonadCont (StateT s m) where-    callCC f = StateT $ \s ->-        callCC $ \c ->-        runStateT (f (\a -> StateT $ \s' -> c (a, s'))) s--instance (MonadError e m) => MonadError e (StateT s m) where-    throwError       = lift . throwError-    m `catchError` h = StateT $ \s -> runStateT m s-        `catchError` \e -> runStateT (h e) s---- Needs UndecidableInstances-instance (MonadReader r m) => MonadReader r (StateT s m) where-    ask       = lift ask-    local f m = StateT $ \s -> local f (runStateT m s)---- Needs UndecidableInstances-instance (MonadWriter w m) => MonadWriter w (StateT s m) where-    tell     = lift . tell-    listen m = StateT $ \s -> do-        ~((a, s'), w) <- listen (runStateT m s)-        return ((a, w), s')-    pass   m = StateT $ \s -> pass $ do-        ~((a, f), s') <- runStateT m s-        return ((a, s'), f)+import Control.Monad.Trans.State.Lazy+        (State, runState, evalState, execState, mapState, withState,+         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,12 +1,10 @@-{-# LANGUAGE UndecidableInstances #-}--- Search for UndecidableInstances to see why this is needed-+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.State.Strict -- Copyright   :  (c) Andy Gill 2001,---           (c) Oregon Graduate Institute of Science and Technology, 2001--- License     :  BSD-style (see the file libraries/base/LICENSE)+--                (c) Oregon Graduate Institute of Science and Technology, 2001+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental@@ -15,214 +13,43 @@ -- Strict state monads. -- --      This module is inspired by the paper---      /Functional Programming with Overloading and---          Higher-Order Polymorphism/,+--      /Functional Programming with Overloading and Higher-Order Polymorphism/, --        Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>) --          Advanced School of Functional Programming, 1995.------ See below for examples.  -----------------------------------------------------------------------------  module Control.Monad.State.Strict (-    module Control.Monad.State.Class,-    -- * The State Monad-    State(..),+    -- * MonadState class+    MonadState.MonadState(..),+    MonadState.modify,+    MonadState.modify',+    MonadState.gets,+    -- * The State monad+    State,+    runState,     evalState,     execState,     mapState,     withState,-    -- * The StateT Monad-    StateT(..),+    -- * The StateT monad transformer+    StateT(StateT),+    runStateT,     evalStateT,     execStateT,     mapStateT,     withStateT,-    module Control.Monad,-    module Control.Monad.Fix,     module Control.Monad.Trans,     -- * Examples     -- $examples   ) where -import Control.Monad-import Control.Monad.Cont.Class-import Control.Monad.Error.Class-import Control.Monad.Fix-import Control.Monad.Reader.Class-import Control.Monad.State.Class+import qualified Control.Monad.State.Class as MonadState import Control.Monad.Trans-import Control.Monad.Writer.Class --- ------------------------------------------------------------------------------ | A parameterizable state monad where /s/ is the type of the state--- to carry and /a/ is the type of the /return value/.--newtype State s a = State { runState :: s -> (a, s) }---- |Evaluate this state monad with the given initial state,throwing--- away the final state.  Very much like @fst@ composed with--- @runstate@.--evalState :: State s a -- ^The state to evaluate-          -> s         -- ^An initial value-          -> a         -- ^The return value of the state application-evalState m s = fst (runState m s)---- |Execute this state and return the new state, throwing away the--- return value.  Very much like @snd@ composed with--- @runstate@.--execState :: State s a -- ^The state to evaluate-          -> s         -- ^An initial value-          -> s         -- ^The new state-execState m s = snd (runState m s)---- |Map a stateful computation from one (return value, state) pair to--- another.  For instance, to convert numberTree from a function that--- returns a tree to a function that returns the sum of the numbered--- tree (see the Examples section for numberTree and sumTree) you may--- write:------ > sumNumberedTree :: (Eq a) => Tree a -> State (Table a) Int--- > sumNumberedTree = mapState (\ (t, tab) -> (sumTree t, tab))  . numberTree--mapState :: ((a, s) -> (b, s)) -> State s a -> State s b-mapState f m = State $ f . runState m---- |Apply this function to this state and return the resulting state.-withState :: (s -> s) -> State s a -> State s a-withState f m = State $ runState m . f---instance Functor (State s) where-    fmap f m = State $ \s -> case runState m s of-                                 (a, s') -> (f a, s')--instance Monad (State s) where-    return a = State $ \s -> (a, s)-    m >>= k  = State $ \s -> case runState m s of-                                 (a, s') -> runState (k a) s'--instance MonadFix (State s) where-    mfix f = State $ \s -> let (a, s') = runState (f a) s in (a, s')--instance MonadState s (State s) where-    get   = State $ \s -> (s, s)-    put s = State $ \_ -> ((), s)---- ------------------------------------------------------------------------------ | A parameterizable state monad for encapsulating an inner--- monad.------ The StateT Monad structure is parameterized over two things:------   * s - The state.------   * m - The inner monad.------ Here are some examples of use:------ (Parser from ParseLib with Hugs)------ >  type Parser a = StateT String [] a--- >     ==> StateT (String -> [(a,String)])------ For example, item can be written as:------ >   item = do (x:xs) <- get--- >          put xs--- >          return x--- >--- >   type BoringState s a = StateT s Indentity a--- >        ==> StateT (s -> Identity (a,s))--- >--- >   type StateWithIO s a = StateT s IO a--- >        ==> StateT (s -> IO (a,s))--- >--- >   type StateWithErr s a = StateT s Maybe a--- >        ==> StateT (s -> Maybe (a,s))--newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }---- |Similar to 'evalState'-evalStateT :: (Monad m) => StateT s m a -> s -> m a-evalStateT m s = do-    (a, _) <- runStateT m s-    return a---- |Similar to 'execState'-execStateT :: (Monad m) => StateT s m a -> s -> m s-execStateT m s = do-    (_, s') <- runStateT m s-    return s'---- |Similar to 'mapState'-mapStateT :: (m (a, s) -> n (b, s)) -> StateT s m a -> StateT s n b-mapStateT f m = StateT $ f . runStateT m---- |Similar to 'withState'-withStateT :: (s -> s) -> StateT s m a -> StateT s m a-withStateT f m = StateT $ runStateT m . f--instance (Monad m) => Functor (StateT s m) where-    fmap f m = StateT $ \s -> do-        (x, s') <- runStateT m s-        return (f x, s')--instance (Monad m) => Monad (StateT s m) where-    return a = StateT $ \s -> return (a, s)-    m >>= k  = StateT $ \s -> do-        (a, s') <- runStateT m s-        runStateT (k a) s'-    fail str = StateT $ \_ -> fail str--instance (MonadPlus m) => MonadPlus (StateT s m) where-    mzero       = StateT $ \_ -> mzero-    m `mplus` n = StateT $ \s -> runStateT m s `mplus` runStateT n s--instance (MonadFix m) => MonadFix (StateT s m) where-    mfix f = StateT $ \s -> mfix $ \ ~(a, _) -> runStateT (f a) s--instance (Monad m) => MonadState s (StateT s m) where-    get   = StateT $ \s -> return (s, s)-    put s = StateT $ \_ -> return ((), s)---- ------------------------------------------------------------------------------ Instances for other mtl transformers--instance MonadTrans (StateT s) where-    lift m = StateT $ \s -> do-        a <- m-        return (a, s)--instance (MonadIO m) => MonadIO (StateT s m) where-    liftIO = lift . liftIO--instance (MonadCont m) => MonadCont (StateT s m) where-    callCC f = StateT $ \s ->-        callCC $ \c ->-        runStateT (f (\a -> StateT $ \s' -> c (a, s'))) s--instance (MonadError e m) => MonadError e (StateT s m) where-    throwError       = lift . throwError-    m `catchError` h = StateT $ \s -> runStateT m s-        `catchError` \e -> runStateT (h e) s---- Needs UndecidableInstances-instance (MonadReader r m) => MonadReader r (StateT s m) where-    ask       = lift ask-    local f m = StateT $ \s -> local f (runStateT m s)---- Needs UndecidableInstances-instance (MonadWriter w m) => MonadWriter w (StateT s m) where-    tell     = lift . tell-    listen m = StateT $ \s -> do-        ((a, s'), w) <- listen (runStateT m s)-        return ((a, w), s')-    pass   m = StateT $ \s -> pass $ do-        ((a, f), s') <- runStateT m s-        return ((a, s'), f)+import Control.Monad.Trans.State.Strict+        (State, runState, evalState, execState, mapState, withState,+         StateT(StateT), runStateT, evalStateT, execStateT, mapStateT, withStateT)  -- --------------------------------------------------------------------------- -- $examples
Control/Monad/Trans.hs view
@@ -1,40 +1,35 @@+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.Trans -- Copyright   :  (c) Andy Gill 2001, --                (c) Oregon Graduate Institute of Science and Technology, 2001--- License     :  BSD-style (see the file libraries/base/LICENSE)+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental -- Portability :  portable ----- The MonadTrans class.+-- Classes for monad transformers. -----      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.+-- A monad transformer makes new monad out of an existing monad, such+-- that computations of the old monad may be embedded in the new one.+-- To construct a monad with a desired set of features, one typically+-- starts with a base monad, such as @Identity@, @[]@ or 'IO', and+-- applies a sequence of monad transformers.+--+-- Most monad transformer modules include the special case of applying the+-- transformer to @Identity@.  For example, @State s@ is an abbreviation+-- for @StateT s Identity@.+--+-- Each monad transformer also comes with an operation @run@/XXX/ to+-- unwrap the transformer, exposing a computation of the inner monad. -----------------------------------------------------------------------------  module Control.Monad.Trans (-    MonadTrans(..),-    MonadIO(..),+    module Control.Monad.Trans.Class,+    module Control.Monad.IO.Class   ) where --- ------------------------------------------------------------------------------ MonadTrans class------ Monad to facilitate stackable Monads.--- Provides a way of digging into an outer--- monad, giving access to (lifting) the inner monad.--class MonadTrans t where-    lift :: Monad m => m a -> t m a--class (Monad m) => MonadIO m where-    liftIO :: IO a -> m a--instance MonadIO IO where-    liftIO = id+import Control.Monad.IO.Class+import Control.Monad.Trans.Class
Control/Monad/Writer.hs view
@@ -1,12 +1,11 @@-{-# LANGUAGE UndecidableInstances #-}--- Search for UndecidableInstances to see why this is needed+{-# LANGUAGE Safe #-}  ----------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.Writer -- Copyright   :  (c) Andy Gill 2001, --                (c) Oregon Graduate Institute of Science and Technology, 2001--- License     :  BSD-style (see the file libraries/base/LICENSE)+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental@@ -15,8 +14,7 @@ -- The MonadWriter class. -- --      Inspired by the paper---      /Functional Programming with Overloading and---          Higher-Order Polymorphism/,+--      /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. -----------------------------------------------------------------------------@@ -26,4 +24,3 @@   ) where  import Control.Monad.Writer.Lazy-
+ 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 @@ -6,7 +10,7 @@ -- Module      :  Control.Monad.Writer.Class -- Copyright   :  (c) Andy Gill 2001, --                (c) Oregon Graduate Institute of Science and Technology, 2001--- License     :  BSD-style (see the file libraries/base/LICENSE)+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental@@ -15,8 +19,7 @@ -- The MonadWriter class. -- --      Inspired by the paper---      /Functional Programming with Overloading and---          Higher-Order Polymorphism/,+--      /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. -----------------------------------------------------------------------------@@ -27,14 +30,32 @@     censor,   ) where -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, 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 Data.Functor.Product (Product(..))  -- --------------------------------------------------------------------------- -- MonadWriter class -- -- tell is like tell on the MUD's it shouts to monad -- what you want to be heard. The monad carries this 'packet'--- upwards, merging it if needed (hence the Monoid requirement)}+-- upwards, merging it if needed (hence the Monoid requirement). -- -- listen listens to a monad acting, and returns what the monad "said". --@@ -42,17 +63,153 @@ -- 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+      tell w+      return a++    -- | @'tell' w@ is an action that produces the output @w@.     tell   :: w -> m ()+    tell w = writer ((),w)++    -- | @'listen' m@ is an action that executes the action @m@ and adds+    -- its output to the value of the computation.     listen :: m a -> m (a, w)+    -- | @'pass' m@ is an action that executes the action @m@, which+    -- returns a value and a function, and returns the value, applying+    -- the function to the output.     pass   :: m (a, w -> w) -> m a -listens :: (MonadWriter w m) => (w -> b) -> m a -> m (a, b)+-- | @'listens' f m@ is an action that executes the action @m@ and adds+-- the result of applying @f@ to the output to the value of the computation.+--+-- * @'listens' f m = 'liftM' (id *** f) ('listen' m)@+listens :: MonadWriter w m => (w -> b) -> m a -> m (a, b) listens f m = do     ~(a, w) <- listen m     return (a, f w) -censor :: (MonadWriter w m) => (w -> w) -> m a -> m a+-- | @'censor' f m@ is an action that executes the action @m@ and+-- applies the function @f@ to its output, leaving the return value+-- unchanged.+--+-- * @'censor' f m = 'pass' ('liftM' (\\x -> (x,f)) m)@+censor :: MonadWriter w m => (w -> w) -> m a -> m a censor f m = pass $ do     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+    listen = Lazy.listen+    pass   = Lazy.pass++instance (Monoid w, Monad m) => MonadWriter w (Strict.WriterT w m) where+    writer = Strict.writer+    tell   = Strict.tell+    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+    listen = LazyRWS.listen+    pass   = LazyRWS.pass++instance (Monoid w, Monad m) => MonadWriter w (StrictRWS.RWST r w s m) where+    writer = StrictRWS.writer+    tell   = StrictRWS.tell+    listen = StrictRWS.listen+    pass   = StrictRWS.pass++-- ---------------------------------------------------------------------------+-- Instances for other mtl transformers+--+-- All of these instances need UndecidableInstances,+-- because they do not satisfy the coverage condition.++-- | @since 2.2+instance MonadWriter w m => MonadWriter w (ExceptT e m) where+    writer = lift . writer+    tell   = lift . tell+    listen = Except.liftListen listen+    pass   = Except.liftPass pass++instance MonadWriter w m => MonadWriter w (IdentityT m) where+    writer = lift . writer+    tell   = lift . tell+    listen = Identity.mapIdentityT listen+    pass   = Identity.mapIdentityT pass++instance MonadWriter w m => MonadWriter w (MaybeT m) where+    writer = lift . writer+    tell   = lift . tell+    listen = Maybe.liftListen listen+    pass   = Maybe.liftPass pass++instance MonadWriter w m => MonadWriter w (ReaderT r m) where+    writer = lift . writer+    tell   = lift . tell+    listen = mapReaderT listen+    pass   = mapReaderT pass++instance MonadWriter w m => MonadWriter w (Lazy.StateT s m) where+    writer = lift . writer+    tell   = lift . tell+    listen = Lazy.liftListen listen+    pass   = Lazy.liftPass pass++instance MonadWriter w m => MonadWriter w (Strict.StateT s m) where+    writer = lift . writer+    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,12 +1,10 @@-{-# LANGUAGE UndecidableInstances #-}--- Search for UndecidableInstances to see why this is needed-+{-# LANGUAGE Safe #-} ----------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.Writer.Lazy -- Copyright   :  (c) Andy Gill 2001, --                (c) Oregon Graduate Institute of Science and Technology, 2001--- License     :  BSD-style (see the file libraries/base/LICENSE)+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental@@ -15,136 +13,31 @@ -- Lazy writer monads. -- --      Inspired by the paper---      /Functional Programming with Overloading and---          Higher-Order Polymorphism/,+--      /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. -----------------------------------------------------------------------------  module Control.Monad.Writer.Lazy (-    module Control.Monad.Writer.Class,-    Writer(..),+    -- * MonadWriter class+    MonadWriter.MonadWriter(..),+    MonadWriter.listens,+    MonadWriter.censor,+    -- * The Writer monad+    Writer,+    runWriter,     execWriter,     mapWriter,-    WriterT(..),+    -- * The WriterT monad transformer+    WriterT(WriterT),+    runWriterT,     execWriterT,     mapWriterT,-    module Control.Monad,-    module Control.Monad.Fix,     module Control.Monad.Trans,-    module Data.Monoid,   ) where -import Control.Monad-import Control.Monad.Cont.Class-import Control.Monad.Error.Class-import Control.Monad.Fix-import Control.Monad.Reader.Class-import Control.Monad.State.Class+import qualified Control.Monad.Writer.Class as MonadWriter import Control.Monad.Trans-import Control.Monad.Writer.Class-import Data.Monoid---- ------------------------------------------------------------------------------ Our parameterizable writer monad--newtype Writer w a = Writer { runWriter :: (a, w) }--execWriter :: Writer w a -> w-execWriter m = snd (runWriter m)--mapWriter :: ((a, w) -> (b, w')) -> Writer w a -> Writer w' b-mapWriter f m = Writer $ f (runWriter m)--instance Functor (Writer w) where-    fmap f m = Writer $ let (a, w) = runWriter m in (f a, w)--instance (Monoid w) => Monad (Writer w) where-    return a = Writer (a, mempty)-    m >>= k  = Writer $ let-        (a, w)  = runWriter m-        (b, w') = runWriter (k a)-        in (b, w `mappend` w')--instance (Monoid w) => MonadFix (Writer w) where-    mfix m = Writer $ let (a, w) = runWriter (m a) in (a, w)--instance (Monoid w) => MonadWriter w (Writer w) where-    tell   w = Writer ((), w)-    listen m = Writer $ let (a, w) = runWriter m in ((a, w), w)-    pass   m = Writer $ let ((a, f), w) = runWriter m in (a, f w)---- ------------------------------------------------------------------------------ Our parameterizable writer monad, with an inner monad--newtype WriterT w m a = WriterT { runWriterT :: m (a, w) }--execWriterT :: Monad m => WriterT w m a -> m w-execWriterT m = do-    ~(_, w) <- runWriterT m-    return w--mapWriterT :: (m (a, w) -> n (b, w')) -> WriterT w m a -> WriterT w' n b-mapWriterT f m = WriterT $ f (runWriterT m)--instance (Monad m) => Functor (WriterT w m) where-    fmap f m = WriterT $ do-        ~(a, w) <- runWriterT m-        return (f a, w)--instance (Monoid w, Monad m) => Monad (WriterT w m) where-    return a = WriterT $ return (a, mempty)-    m >>= k  = WriterT $ do-        ~(a, w)  <- runWriterT m-        ~(b, w') <- runWriterT (k a)-        return (b, w `mappend` w')-    fail msg = WriterT $ fail msg--instance (Monoid w, MonadPlus m) => MonadPlus (WriterT w m) where-    mzero       = WriterT mzero-    m `mplus` n = WriterT $ runWriterT m `mplus` runWriterT n--instance (Monoid w, MonadFix m) => MonadFix (WriterT w m) where-    mfix m = WriterT $ mfix $ \ ~(a, _) -> runWriterT (m a)--instance (Monoid w, Monad m) => MonadWriter w (WriterT w m) where-    tell   w = WriterT $ return ((), w)-    listen m = WriterT $ do-        ~(a, w) <- runWriterT m-        return ((a, w), w)-    pass   m = WriterT $ do-        ~((a, f), w) <- runWriterT m-        return (a, f w)---- ------------------------------------------------------------------------------ Instances for other mtl transformers--instance (Monoid w) => MonadTrans (WriterT w) where-    lift m = WriterT $ do-        a <- m-        return (a, mempty)--instance (Monoid w, MonadIO m) => MonadIO (WriterT w m) where-    liftIO = lift . liftIO--instance (Monoid w, MonadCont m) => MonadCont (WriterT w m) where-    callCC f = WriterT $-        callCC $ \c ->-        runWriterT (f (\a -> WriterT $ c (a, mempty)))--instance (Monoid w, MonadError e m) => MonadError e (WriterT w m) where-    throwError       = lift . throwError-    m `catchError` h = WriterT $ runWriterT m-        `catchError` \e -> runWriterT (h e)---- This instance needs UndecidableInstances, because--- it does not satisfy the coverage condition-instance (Monoid w, MonadReader r m) => MonadReader r (WriterT w m) where-    ask       = lift ask-    local f m = WriterT $ local f (runWriterT m)---- Needs UndecidableInstances-instance (Monoid w, MonadState s m) => MonadState s (WriterT w m) where-    get = lift get-    put = lift . put-+import Control.Monad.Trans.Writer.Lazy (+        Writer, runWriter, execWriter, mapWriter,+        WriterT(WriterT), runWriterT, execWriterT, mapWriterT)
Control/Monad/Writer/Strict.hs view
@@ -1,12 +1,10 @@-{-# LANGUAGE UndecidableInstances #-}--- Search for UndecidableInstances to see why this is needed-+{-# 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 libraries/base/LICENSE)+-- License     :  BSD-style (see the file LICENSE) -- -- Maintainer  :  libraries@haskell.org -- Stability   :  experimental@@ -15,138 +13,30 @@ -- Strict writer monads. -- --      Inspired by the paper---      /Functional Programming with Overloading and---          Higher-Order Polymorphism/,+--      /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. -----------------------------------------------------------------------------  module Control.Monad.Writer.Strict (-    module Control.Monad.Writer.Class,-    Writer(..),+    -- * MonadWriter class+    MonadWriter.MonadWriter(..),+    MonadWriter.listens,+    MonadWriter.censor,+    -- * The Writer monad+    Writer,+    runWriter,     execWriter,     mapWriter,+    -- * The WriterT monad transformer     WriterT(..),     execWriterT,     mapWriterT,-    module Control.Monad,-    module Control.Monad.Fix,     module Control.Monad.Trans,-    module Data.Monoid,   ) where -import Control.Monad-import Control.Monad.Cont.Class-import Control.Monad.Error.Class-import Control.Monad.Fix-import Control.Monad.Reader.Class-import Control.Monad.State.Class+import qualified Control.Monad.Writer.Class as MonadWriter import Control.Monad.Trans-import Control.Monad.Writer.Class-import Data.Monoid---- ------------------------------------------------------------------------------ Our parameterizable writer monad--newtype Writer w a = Writer { runWriter :: (a, w) }--execWriter :: Writer w a -> w-execWriter m = snd (runWriter m)--mapWriter :: ((a, w) -> (b, w')) -> Writer w a -> Writer w' b-mapWriter f m = Writer $ f (runWriter m)--instance Functor (Writer w) where-    fmap f m = Writer $ case runWriter m of-                            (a, w) -> (f a, w)--instance (Monoid w) => Monad (Writer w) where-    return a = Writer (a, mempty)-    m >>= k  = Writer $ case runWriter m of-                            (a, w) -> case runWriter (k a) of-                                (b, w') -> (b, w `mappend` w')--instance (Monoid w) => MonadFix (Writer w) where-    mfix m = Writer $ let (a, w) = runWriter (m a) in (a, w)--instance (Monoid w) => MonadWriter w (Writer w) where-    tell   w = Writer ((), w)-    listen m = Writer $ case runWriter m of-                            (a, w) -> ((a, w), w)-    pass   m = Writer $ case runWriter m of-                            ((a, f), w) -> (a, f w)---- ------------------------------------------------------------------------------ Our parameterizable writer monad, with an inner monad--newtype WriterT w m a = WriterT { runWriterT :: m (a, w) }--execWriterT :: Monad m => WriterT w m a -> m w-execWriterT m = do-    (_, w) <- runWriterT m-    return w--mapWriterT :: (m (a, w) -> n (b, w')) -> WriterT w m a -> WriterT w' n b-mapWriterT f m = WriterT $ f (runWriterT m)--instance (Monad m) => Functor (WriterT w m) where-    fmap f m = WriterT $ do-        (a, w) <- runWriterT m-        return (f a, w)--instance (Monoid w, Monad m) => Monad (WriterT w m) where-    return a = WriterT $ return (a, mempty)-    m >>= k  = WriterT $ do-        (a, w)  <- runWriterT m-        (b, w') <- runWriterT (k a)-        return (b, w `mappend` w')-    fail msg = WriterT $ fail msg--instance (Monoid w, MonadPlus m) => MonadPlus (WriterT w m) where-    mzero       = WriterT mzero-    m `mplus` n = WriterT $ runWriterT m `mplus` runWriterT n--instance (Monoid w, MonadFix m) => MonadFix (WriterT w m) where-    mfix m = WriterT $ mfix $ \ ~(a, _) -> runWriterT (m a)--instance (Monoid w, Monad m) => MonadWriter w (WriterT w m) where-    tell   w = WriterT $ return ((), w)-    listen m = WriterT $ do-        (a, w) <- runWriterT m-        return ((a, w), w)-    pass   m = WriterT $ do-        ((a, f), w) <- runWriterT m-        return (a, f w)---- ------------------------------------------------------------------------------ Instances for other mtl transformers--instance (Monoid w) => MonadTrans (WriterT w) where-    lift m = WriterT $ do-        a <- m-        return (a, mempty)--instance (Monoid w, MonadIO m) => MonadIO (WriterT w m) where-    liftIO = lift . liftIO--instance (Monoid w, MonadCont m) => MonadCont (WriterT w m) where-    callCC f = WriterT $-        callCC $ \c ->-        runWriterT (f (\a -> WriterT $ c (a, mempty)))--instance (Monoid w, MonadError e m) => MonadError e (WriterT w m) where-    throwError       = lift . throwError-    m `catchError` h = WriterT $ runWriterT m-        `catchError` \e -> runWriterT (h e)---- This instance needs UndecidableInstances, because--- it does not satisfy the coverage condition-instance (Monoid w, MonadReader r m) => MonadReader r (WriterT w m) where-    ask       = lift ask-    local f m = WriterT $ local f (runWriterT m)---- Needs UndecidableInstances-instance (Monoid w, MonadState s m) => MonadState s (WriterT w m) where-    get = lift get-    put = lift . put-+import Control.Monad.Trans.Writer.Strict (+        Writer, runWriter, execWriter, mapWriter,+        WriterT(..), execWriterT, mapWriterT)
+ README.markdown view
@@ -0,0 +1,164 @@+# `mtl` [![Hackage](https://img.shields.io/hackage/v/mtl.svg)](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>).
Setup.hs view
@@ -1,6 +1,2 @@-module Main (main) where- import Distribution.Simple--main :: IO () main = defaultMain
mtl.cabal view
@@ -1,27 +1,44 @@-name:         mtl-version:      1.1.1.1-license:      BSD3-license-file: LICENSE-author:       Andy Gill-maintainer:   libraries@haskell.org-category:     Control-synopsis:     Monad transformer library+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:-    A monad transformer library, inspired by the paper /Functional-    Programming with Overloading and Higher-Order Polymorphism/,-    by Mark P Jones (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>),-    Advanced School of Functional Programming, 1995.+  MTL is a collection of monad classes, extending the 'transformers'+  package, using functional dependencies for generic lifting of+  monadic actions.+ build-type: Simple-ghc-options: -Wall-exposed-modules:++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: 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@@ -33,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 < 5-extensions: MultiParamTypeClasses,-            FunctionalDependencies,-            FlexibleInstances,-            TypeSynonymInstances+    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