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