├── .github └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.markdown ├── Control └── Monad │ ├── Accum.hs │ ├── Cont.hs │ ├── Cont │ └── Class.hs │ ├── Error │ └── Class.hs │ ├── Except.hs │ ├── Identity.hs │ ├── RWS.hs │ ├── RWS │ ├── CPS.hs │ ├── Class.hs │ ├── Lazy.hs │ └── Strict.hs │ ├── Reader.hs │ ├── Reader │ └── Class.hs │ ├── Select.hs │ ├── State.hs │ ├── State │ ├── Class.hs │ ├── Lazy.hs │ └── Strict.hs │ ├── Trans.hs │ ├── Writer.hs │ └── Writer │ ├── CPS.hs │ ├── Class.hs │ ├── Lazy.hs │ └── Strict.hs ├── LICENSE ├── README.markdown ├── Setup.hs ├── cabal.project ├── docs └── Mtl-2.3.x-Migration.md └── mtl.cabal /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | # Trigger the workflow on push or pull request, but only for the main branch 4 | on: 5 | pull_request: 6 | push: 7 | branches: ["master"] 8 | 9 | jobs: 10 | native: 11 | name: "Native: GHC ${{ matrix.ghc }} on ${{ matrix.os }}" 12 | runs-on: ${{ matrix.os }} 13 | strategy: 14 | matrix: 15 | os: [ubuntu-latest, macos-latest, windows-latest] 16 | ghc: ['8.6', '8.8', '8.10', '9.0', '9.2', '9.4.1'] 17 | steps: 18 | - name: Checkout base repo 19 | uses: actions/checkout@v2.3.5 20 | - name: Set up Haskell 21 | id: setup-haskell 22 | uses: haskell/actions/setup@v1 23 | with: 24 | ghc-version: ${{ matrix.ghc }} 25 | cabal-version: 'latest' 26 | - name: Configure 27 | run: cabal new-configure 28 | - name: Freeze 29 | run: cabal freeze 30 | - name: Cache 31 | uses: actions/cache@v2.1.3 32 | with: 33 | path: ${{ steps.setup-haskell.outputs.cabal-store }} 34 | key: ${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }} 35 | restore-keys: ${{ runner.os }}-${{ matrix.ghc }}- 36 | - name: Build 37 | run: cabal build 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | dist-boot 3 | dist-install 4 | dist-newstyle 5 | ghc.mk 6 | GNUmakefile 7 | cabal-dev 8 | *.o 9 | *.hi 10 | *.chi 11 | *.chs.h 12 | *.dyn_o 13 | *.dyn_hi 14 | .hpc 15 | .hsenv 16 | .cabal-sandbox/ 17 | cabal.sandbox.config 18 | *.prof 19 | *.aux 20 | *.hp 21 | *.eventlog 22 | .stack-work/ 23 | cabal.project.local* 24 | .HTF/ 25 | .ghc.environment.* 26 | .nvimrc 27 | -------------------------------------------------------------------------------- /CHANGELOG.markdown: -------------------------------------------------------------------------------- 1 | 2.3.1 -- 2022-09-10 2 | ----- 3 | * Add `modifyError` to `Control.Monad.Error.Class`, and re-export from 4 | `Control.Monad.Except`. 5 | * Make the `MonadCont` instance for `ContT` more polykinded; now, `r` is allowed 6 | to be of an arbitrary kind `k`, rather than only `Type`. 7 | * Add a generic `liftCallCC` for use with any `MonadTrans`. 8 | * Add `modifyError` to `Control.Monad.Error.Class` 9 | * Return re-export of `ExceptT` and related functions to `Control.Monad.Except`. 10 | * Add `label` function to `MonadCont` 11 | 12 | 2.3 -- 2022-05-07 13 | --- 14 | * Add instances for `Control.Monad.Trans.Writer.CPS` and 15 | `Control.Monad.Trans.RWS.CPS` from `transformers` 0.5.6 and add 16 | `Control.Monad.Writer.CPS` and `Control.Monad.RWS.CPS`. 17 | * `Control.Monad.Cont` now re-exports `evalCont` and `evalContT`. 18 | * Add `tryError`, `withError`, `handleError`, and `mapError` to 19 | `Control.Monad.Error.Class`, and re-export from `Control.Monad.Except`. 20 | * Remove `Control.Monad.List` and `Control.Monad.Error`. 21 | * Remove instances of deprecated `ListT` and `ErrorT`. 22 | * Remove re-exports of `Error`. 23 | * Add instances for `Control.Monad.Trans.Accum` and 24 | `Control.Monad.Trans.Select`. 25 | * Require GHC 8.6 or higher, and `cabal-install` 3.0 or higher. 26 | * Require `transformers-0.5.6` or higher. 27 | * Add `Control.Monad.Accum` for the `MonadAccum` type class, as well as the 28 | `LiftingAccum` deriving helper. 29 | * Add `Control.Monad.Select` for the `MonadSelect` type class, as well as the 30 | `LiftingSelect` deriving helper. 31 | * Remove re-exports of `Control.Monad`, `Control.Monad.Fix` and `Data.Monoid` modules 32 | 33 | 2.2.2 -- 2018-02-24 34 | ----- 35 | * `Control.Monad.Identity` now re-exports `Control.Monad.Trans.Identity` 36 | * Fix a bug in which `Control.Monad.State.Class.modify'` was not as strict in 37 | the new state as its counterparts in `transformers` 38 | * Add a `MonadError () Maybe` instance 39 | * Add `liftEither :: MonadError e m => Either e a -> m a` to 40 | `Control.Monad.Except{.Class}` 41 | * Add a `MonadWriter w ((,) w)` instance (when built against `base-4.9` or later) 42 | 43 | 2.2.1 -- 2014-06-02 44 | ------- 45 | * Provide MINIMAL pragmas for `MonadState`, `MonadWriter`, `MonadReader` 46 | * Added a cyclic definition of `ask` in terms of `reader` for consistency with `get`/`put` vs. `state` and `tell` vs. `writer` 47 | * Fix deprecation warnings caused by `transformers` 0.4 deprecating `ErrorT`. 48 | * Added `Control.Monad.Except` in the style of the other `mtl` re-export modules 49 | 50 | 2.2.0.1 -- 2014-05-05 51 | ------- 52 | * 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! 53 | 54 | 2.2 -- 2014-05-05 55 | --- 56 | * `transformers` 0.4 support 57 | * Added instances for `ExceptT` 58 | * Added `modify'` to `Control.Monad.State.*` 59 | 60 | 2.1.3.1 -- 2014-03-24 61 | ------- 62 | * Avoid importing `Control.Monad.Instances` on GHC 7.8 to build without deprecation warnings. 63 | 64 | 2.1.3 65 | ----- 66 | * Removed the now-irrelevant `Error` constraint from the `MonadError` instance for `Either e`. 67 | -------------------------------------------------------------------------------- /Control/Monad/Accum.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DerivingVia #-} 2 | {-# LANGUAGE FlexibleInstances #-} 3 | {-# LANGUAGE FunctionalDependencies #-} 4 | {-# LANGUAGE KindSignatures #-} 5 | {-# LANGUAGE ScopedTypeVariables #-} 6 | {-# LANGUAGE StandaloneDeriving #-} 7 | {-# LANGUAGE Trustworthy #-} 8 | {-# LANGUAGE TupleSections #-} 9 | {-# LANGUAGE UndecidableInstances #-} 10 | -- Later GHCs infer DerivingVia as not Safe 11 | -- We just downgrade to Trustworthy and go fish 12 | {-# OPTIONS_GHC -Wno-trustworthy-safe #-} 13 | 14 | -- | Module: Control.Monad.Accum 15 | -- Copyright: (C) Koz Ross 2022, Manuel Bärenz 2021 16 | -- License: BSD-3-Clause (see the LICENSE file) 17 | -- Maintainer: koz.ross@retro-freedom.nz 18 | -- Stability: Experimental 19 | -- Portability: GHC only 20 | -- 21 | -- [Computation type:] Accumulation (either append-only state, or writer with 22 | -- the ability to read all previous input). 23 | -- 24 | -- [Binding strategy:] Binding a function to a monadic value monoidally 25 | -- accumulates the subcomputations (that is, using '<>'). 26 | -- 27 | -- [Useful for:] Logging, patch-style tracking. 28 | -- 29 | -- [Zero and plus:] None. 30 | -- 31 | -- [Example type:] @'Control.Monad.Trans.Accum.Accum' w a@ 32 | -- 33 | -- = A note on commutativity 34 | -- 35 | -- Some effects are /commutative/: it doesn't matter which you resolve first, as 36 | -- all possible orderings of commutative effects are isomorphic. Consider, for 37 | -- example, the reader and state effects, as exemplified by 'ReaderT' and 38 | -- 'StrictState.StateT' respectively. If we have 39 | -- @'ReaderT' r ('StrictState.State' s) a@, this is 40 | -- effectively @r -> 'StrictState.State' s a ~ r -> s -> (a, s)@; if we instead have 41 | -- @'StrictState.StateT' s ('Control.Monad.Trans.Reader.Reader' r) a@, this is effectively 42 | -- @s -> 'Control.Monad.Trans.Reader' r (a, s) ~ s -> r -> (a, s)@. Since we 43 | -- can always reorder function arguments (for example, using 'flip', as in 44 | -- this case) without changing the result, these are 45 | -- isomorphic, showing that reader and state are /commutative/, or, more 46 | -- precisely, /commute with each other/. 47 | -- 48 | -- However, this isn't generally the case. Consider instead the error and state 49 | -- effects, as exemplified by 'MaybeT' and 'StrictState.StateT' respectively. 50 | -- If we have @'MaybeT' ('Control.Monad.Trans.State.Strict.State' s) a@, this 51 | -- is effectively @'State' s ('Maybe' a) ~ s -> ('Maybe' a, s)@: put simply, 52 | -- the error can occur only in the /result/, but 53 | -- not the state, which always \'survives\'. On the other hand, if we have 54 | -- @'StrictState.StateT' s 'Maybe' a@, this is instead @s -> 'Maybe' (a, s)@: here, 55 | -- if we error, we lose /both/ the state and the result! Thus, error and state effects 56 | -- do /not/ commute with each other. 57 | -- 58 | -- As the MTL is capability-based, we support any ordering of non-commutative 59 | -- effects on an equal footing. Indeed, if you wish to use 60 | -- 'Control.Monad.State.Class.MonadState', for 61 | -- example, whether your final monadic stack ends up being @'MaybeT' 62 | -- ('Control.Monad.Trans.State.Strict.State' s) 63 | -- a@, @'StrictState.StateT' s 'Maybe' a@, or anything else, you will be able to write your 64 | -- desired code without having to consider such differences. However, the way we 65 | -- /implement/ these capabilities for any given transformer (or rather, any 66 | -- given transformed stack) /is/ affected by this ordering unless the effects in 67 | -- question are commutative. 68 | -- 69 | -- We note in this module which effects the accumulation effect does and doesn't 70 | -- commute with; we also note on implementations with non-commutative 71 | -- transformers what the outcome will be. Note that, depending on how the 72 | -- \'inner monad\' is structured, this may be more complex than we note: we 73 | -- describe only what impact the \'outer effect\' has, not what else might be in 74 | -- the stack. 75 | -- 76 | -- = Commutativity of accumulation 77 | -- 78 | -- The accumulation effect commutes with the identity effect ('IdentityT'), 79 | -- reader, writer or state effects ('ReaderT', 'StrictWriter.WriterT', 'StrictState.StateT' and any 80 | -- combination, including 'StrictRWS.RWST' for example) and with itself. It does /not/ 81 | -- commute with anything else. 82 | module Control.Monad.Accum 83 | ( -- * Type class 84 | MonadAccum (..), 85 | 86 | -- * Lifting helper type 87 | LiftingAccum (..), 88 | 89 | -- * Other functions 90 | looks, 91 | ) 92 | where 93 | 94 | import Control.Monad.Trans.Accum (AccumT) 95 | import qualified Control.Monad.Trans.Accum as Accum 96 | import Control.Monad.Trans.Class (MonadTrans (lift)) 97 | import Control.Monad.Trans.Cont (ContT) 98 | import Control.Monad.Trans.Except (ExceptT) 99 | import Control.Monad.Trans.Identity (IdentityT) 100 | import Control.Monad.Trans.Maybe (MaybeT) 101 | import qualified Control.Monad.Trans.RWS.CPS as CPSRWS 102 | import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS 103 | import qualified Control.Monad.Trans.RWS.Strict as StrictRWS 104 | import Control.Monad.Trans.Reader (ReaderT) 105 | import Control.Monad.Trans.Select (SelectT) 106 | import qualified Control.Monad.Trans.State.Lazy as LazyState 107 | import qualified Control.Monad.Trans.State.Strict as StrictState 108 | import qualified Control.Monad.Trans.Writer.CPS as CPSWriter 109 | import qualified Control.Monad.Trans.Writer.Lazy as LazyWriter 110 | import qualified Control.Monad.Trans.Writer.Strict as StrictWriter 111 | import Data.Functor (($>)) 112 | import Data.Functor.Identity (Identity) 113 | import Data.Kind (Type) 114 | 115 | -- | The capability to accumulate. This can be seen in one of two ways: 116 | -- 117 | -- * A 'Control.Monad.State.Class.MonadState' which can only append (using '<>'); or 118 | -- * A 'Control.Monad.Writer.Class.MonadWriter' (limited to 119 | -- 'Control.Monad.Writer.Class.tell') with the ability to view the result of all previous 120 | -- 'Control.Monad.Writer.Class.tell's. 121 | -- 122 | -- = Laws 123 | -- 124 | -- 'accum' should obey the following: 125 | -- 126 | -- 1. @'accum' ('const' (x, 'mempty'))@ @=@ @'pure' x@ 127 | -- 2. @'accum' f '*>' 'accum' g@ @=@ 128 | -- @'accum' '$' \acc -> let (_, v) = f acc 129 | -- (res, w) = g (acc '<>' v) in (res, v '<>' w)@ 130 | -- 131 | -- If you choose to define 'look' and 'add' instead, their definitions must obey 132 | -- the following: 133 | -- 134 | -- 1. @'look' '*>' 'look'@ @=@ @'look'@ 135 | -- 2. @'add' 'mempty'@ @=@ @'pure' ()@ 136 | -- 3. @'add' x '*>' 'add' y@ @=@ @'add' (x '<>' y)@ 137 | -- 4. @'add' x '*>' 'look'@ @=@ @'look' '>>=' \w -> 'add' x '$>' w '<>' x@ 138 | -- 139 | -- If you want to define both, the relationship between them is as follows. 140 | -- These are also the default definitions. 141 | -- 142 | -- 1. @'look'@ @=@ @'accum' '$' \acc -> (acc, mempty)@ 143 | -- 2. @'add' x@ @=@ @'accum' '$' \acc -> ('()', x)@ 144 | -- 3. @'accum' f@ @=@ @'look' >>= \acc -> let (res, v) = f acc in 'add' v '$>' res@ 145 | -- 146 | -- @since 2.3 147 | class (Monoid w, Monad m) => MonadAccum w m | m -> w where 148 | -- | Retrieve the accumulated result so far. 149 | look :: m w 150 | look = accum (,mempty) 151 | 152 | -- | Append a value to the result. 153 | add :: w -> m () 154 | add x = accum $ const ((), x) 155 | 156 | -- | Embed a simple accumulation action into the monad. 157 | accum :: (w -> (a, w)) -> m a 158 | accum f = look >>= \acc -> let (res, v) = f acc in add v $> res 159 | 160 | {-# MINIMAL accum | look, add #-} 161 | 162 | -- | @since 2.3 163 | instance (Monoid w) => MonadAccum w (AccumT w Identity) where 164 | look = Accum.look 165 | add = Accum.add 166 | accum = Accum.accum 167 | 168 | -- | The accumulated value \'survives\' an error: even if the 169 | -- computation fails to deliver a result, we still have an accumulated value. 170 | -- 171 | -- @since 2.3 172 | deriving via 173 | (LiftingAccum MaybeT m) 174 | instance 175 | (MonadAccum w m) => 176 | MonadAccum w (MaybeT m) 177 | 178 | -- | The continuation can see, and interact with, the accumulated value. 179 | -- 180 | -- @since 2.3 181 | deriving via 182 | (LiftingAccum (ContT r) m) 183 | instance 184 | (MonadAccum w m) => 185 | MonadAccum w (ContT r m) 186 | 187 | -- | The accumulated value \'survives\' an exception: even if the computation 188 | -- fails to deliver a result, we still have an accumulated value. 189 | -- 190 | -- @since 2.3 191 | deriving via 192 | (LiftingAccum (ExceptT e) m) 193 | instance 194 | (MonadAccum w m) => 195 | MonadAccum w (ExceptT e m) 196 | 197 | -- | @since 2.3 198 | deriving via 199 | (LiftingAccum IdentityT m) 200 | instance 201 | (MonadAccum w m) => 202 | MonadAccum w (IdentityT m) 203 | 204 | -- | @since 2.3 205 | deriving via 206 | (LiftingAccum (CPSRWS.RWST r w s) m) 207 | instance 208 | (MonadAccum w' m) => 209 | MonadAccum w' (CPSRWS.RWST r w s m) 210 | 211 | -- | @since 2.3 212 | deriving via 213 | (LiftingAccum (LazyRWS.RWST r w s) m) 214 | instance 215 | (MonadAccum w' m, Monoid w) => 216 | MonadAccum w' (LazyRWS.RWST r w s m) 217 | 218 | -- | @since 2.3 219 | deriving via 220 | (LiftingAccum (StrictRWS.RWST r w s) m) 221 | instance 222 | (MonadAccum w' m, Monoid w) => 223 | MonadAccum w' (StrictRWS.RWST r w s m) 224 | 225 | -- | @since 2.3 226 | deriving via 227 | (LiftingAccum (ReaderT r) m) 228 | instance 229 | (MonadAccum w m) => 230 | MonadAccum w (ReaderT r m) 231 | 232 | -- | The \'ranking\' function gains the ability to accumulate @w@s each time it 233 | -- is called. The final result will include the entire log of all such calls. 234 | -- 235 | -- @since 2.3 236 | deriving via 237 | (LiftingAccum (SelectT r) m) 238 | instance 239 | (MonadAccum w m) => 240 | MonadAccum w (SelectT r m) 241 | 242 | -- | @since 2.3 243 | deriving via 244 | (LiftingAccum (LazyState.StateT s) m) 245 | instance 246 | (MonadAccum w m) => 247 | MonadAccum w (LazyState.StateT s m) 248 | 249 | -- | @since 2.3 250 | deriving via 251 | (LiftingAccum (StrictState.StateT s) m) 252 | instance 253 | (MonadAccum w m) => 254 | MonadAccum w (StrictState.StateT s m) 255 | 256 | -- | @since 2.3 257 | deriving via 258 | (LiftingAccum (CPSWriter.WriterT w) m) 259 | instance 260 | (MonadAccum w' m) => 261 | MonadAccum w' (CPSWriter.WriterT w m) 262 | 263 | -- | @since 2.3 264 | deriving via 265 | (LiftingAccum (LazyWriter.WriterT w) m) 266 | instance 267 | (MonadAccum w' m, Monoid w) => 268 | MonadAccum w' (LazyWriter.WriterT w m) 269 | 270 | -- | @since 2.3 271 | deriving via 272 | (LiftingAccum (StrictWriter.WriterT w) m) 273 | instance 274 | (MonadAccum w' m, Monoid w) => 275 | MonadAccum w' (StrictWriter.WriterT w m) 276 | 277 | -- | A helper type to decrease boilerplate when defining new transformer 278 | -- instances of 'MonadAccum'. 279 | -- 280 | -- Most of the instances in this module are derived using this method; for 281 | -- example, our instance of 'ExceptT' is derived as follows: 282 | -- 283 | -- > deriving via (LiftingAccum (ExceptT e) m) instance (MonadAccum w m) => 284 | -- > MonadAccum w (ExceptT e m) 285 | -- 286 | -- @since 2.3 287 | newtype LiftingAccum (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) (a :: Type) 288 | = LiftingAccum (t m a) 289 | deriving 290 | ( -- | @since 2.3 291 | Functor, 292 | -- | @since 2.3 293 | Applicative, 294 | -- | @since 2.3 295 | Monad 296 | ) 297 | via (t m) 298 | 299 | -- | @since 2.3 300 | instance (MonadTrans t, Monad (t m), MonadAccum w m) => MonadAccum w (LiftingAccum t m) where 301 | look = LiftingAccum . lift $ look 302 | add x = LiftingAccum . lift $ add x 303 | accum f = LiftingAccum . lift $ accum f 304 | 305 | -- | Retrieve a function of the accumulated value. 306 | -- 307 | -- @since 2.3 308 | looks :: 309 | forall (a :: Type) (m :: Type -> Type) (w :: Type). 310 | (MonadAccum w m) => 311 | (w -> a) -> 312 | m a 313 | looks f = f <$> look 314 | -------------------------------------------------------------------------------- /Control/Monad/Cont.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | {- | 4 | Module : Control.Monad.Cont 5 | Copyright : (c) The University of Glasgow 2001, 6 | (c) Jeff Newbern 2003-2007, 7 | (c) Andriy Palamarchuk 2007 8 | License : BSD-style (see the file LICENSE) 9 | 10 | Maintainer : libraries@haskell.org 11 | Stability : experimental 12 | Portability : portable 13 | 14 | [Computation type:] Computations which can be interrupted and resumed. 15 | 16 | [Binding strategy:] Binding a function to a monadic value creates 17 | a new continuation which uses the function as the continuation of the monadic 18 | computation. 19 | 20 | [Useful for:] Complex control structures, error handling, 21 | and creating co-routines. 22 | 23 | [Zero and plus:] None. 24 | 25 | [Example type:] @'Cont' r a@ 26 | 27 | The Continuation monad represents computations in continuation-passing style 28 | (CPS). 29 | In continuation-passing style function result is not returned, 30 | but instead is passed to another function, 31 | received as a parameter (continuation). 32 | Computations are built up from sequences 33 | of nested continuations, terminated by a final continuation (often @id@) 34 | which produces the final result. 35 | Since continuations are functions which represent the future of a computation, 36 | manipulation of the continuation functions can achieve complex manipulations 37 | of the future of the computation, 38 | such as interrupting a computation in the middle, aborting a portion 39 | of a computation, restarting a computation, and interleaving execution of 40 | computations. 41 | The Continuation monad adapts CPS to the structure of a monad. 42 | 43 | Before using the Continuation monad, be sure that you have 44 | a firm understanding of continuation-passing style 45 | and that continuations represent the best solution to your particular 46 | design problem. 47 | Many algorithms which require continuations in other languages do not require 48 | them in Haskell, due to Haskell's lazy semantics. 49 | Abuse of the Continuation monad can produce code that is impossible 50 | to understand and maintain. 51 | -} 52 | 53 | module Control.Monad.Cont ( 54 | -- * MonadCont class 55 | MonadCont.MonadCont(..), 56 | MonadCont.label, 57 | MonadCont.label_, 58 | 59 | -- * The Cont monad 60 | Cont.Cont, 61 | Cont.cont, 62 | Cont.runCont, 63 | Cont.evalCont, 64 | Cont.mapCont, 65 | Cont.withCont, 66 | -- * The ContT monad transformer 67 | Cont.ContT(ContT), 68 | Cont.runContT, 69 | Cont.evalContT, 70 | Cont.mapContT, 71 | Cont.withContT, 72 | -- * Example 1: Simple Continuation Usage 73 | -- $simpleContExample 74 | 75 | -- * Example 2: Using @callCC@ 76 | -- $callCCExample 77 | 78 | -- * Example 3: Using @ContT@ Monad Transformer 79 | -- $ContTExample 80 | 81 | -- * Example 4: Using @label@ 82 | -- $labelExample 83 | ) where 84 | 85 | import qualified Control.Monad.Cont.Class as MonadCont 86 | import qualified Control.Monad.Trans.Cont as Cont 87 | 88 | {- $simpleContExample 89 | Calculating length of a list continuation-style: 90 | 91 | >calculateLength :: [a] -> Cont r Int 92 | >calculateLength l = return (length l) 93 | 94 | Here we use @calculateLength@ by making it to pass its result to @print@: 95 | 96 | >main = do 97 | > runCont (calculateLength "123") print 98 | > -- result: 3 99 | 100 | It is possible to chain 'Cont' blocks with @>>=@. 101 | 102 | >double :: Int -> Cont r Int 103 | >double n = return (n * 2) 104 | > 105 | >main = do 106 | > runCont (calculateLength "123" >>= double) print 107 | > -- result: 6 108 | -} 109 | 110 | {- $callCCExample 111 | This example gives a taste of how escape continuations work, shows a typical 112 | pattern for their usage. 113 | 114 | >-- Returns a string depending on the length of the name parameter. 115 | >-- If the provided string is empty, returns an error. 116 | >-- Otherwise, returns a welcome message. 117 | >whatsYourName :: String -> String 118 | >whatsYourName name = 119 | > (`runCont` id) $ do -- 1 120 | > response <- callCC $ \exit -> do -- 2 121 | > validateName name exit -- 3 122 | > return $ "Welcome, " ++ name ++ "!" -- 4 123 | > return response -- 5 124 | > 125 | >validateName name exit = do 126 | > when (null name) (exit "You forgot to tell me your name!") 127 | 128 | Here is what this example does: 129 | 130 | (1) Runs an anonymous 'Cont' block and extracts value from it with 131 | @(\`runCont\` id)@. Here @id@ is the continuation, passed to the @Cont@ block. 132 | 133 | (1) Binds @response@ to the result of the following 'Control.Monad.Cont.Class.callCC' block, 134 | binds @exit@ to the continuation. 135 | 136 | (1) Validates @name@. 137 | This approach illustrates advantage of using 'Control.Monad.Cont.Class.callCC' over @return@. 138 | We pass the continuation to @validateName@, 139 | and interrupt execution of the @Cont@ block from /inside/ of @validateName@. 140 | 141 | (1) Returns the welcome message from the 'Control.Monad.Cont.Class.callCC' block. 142 | This line is not executed if @validateName@ fails. 143 | 144 | (1) Returns from the @Cont@ block. 145 | -} 146 | 147 | {-$ContTExample 148 | 'ContT' can be used to add continuation handling to other monads. 149 | Here is an example how to combine it with @IO@ monad: 150 | 151 | >import Control.Monad.Cont 152 | >import System.IO 153 | > 154 | >main = do 155 | > hSetBuffering stdout NoBuffering 156 | > runContT (callCC askString) reportResult 157 | > 158 | >askString :: (String -> ContT () IO String) -> ContT () IO String 159 | >askString next = do 160 | > liftIO $ putStrLn "Please enter a string" 161 | > s <- liftIO $ getLine 162 | > next s 163 | > 164 | >reportResult :: String -> IO () 165 | >reportResult s = do 166 | > putStrLn ("You entered: " ++ s) 167 | 168 | Action @askString@ requests user to enter a string, 169 | and passes it to the continuation. 170 | @askString@ takes as a parameter a continuation taking a string parameter, 171 | and returning @IO ()@. 172 | Compare its signature to 'runContT' definition. 173 | -} 174 | 175 | {-$labelExample 176 | 177 | The early exit behavior of 'Control.Monad.Cont.Class.callCC' can be leveraged to produce other idioms: 178 | 179 | > whatsYourNameLabel :: IO () 180 | > whatsYourNameLabel = evalContT $ do 181 | > (beginning, attempts) <- label (0 :: Int) 182 | > liftIO $ putStrLn $ "Attempt #" <> show attempts 183 | > liftIO $ putStrLn $ "What's your name?" 184 | > name <- liftIO getLine 185 | > when (null name) $ beginning (attempts + 1) 186 | > liftIO $ putStrLn $ "Welcome, " ++ name ++ "!" 187 | 188 | 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. 189 | -} 190 | -------------------------------------------------------------------------------- /Control/Monad/Cont/Class.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE RankNTypes #-} 2 | {-# LANGUAGE Safe #-} 3 | {-# LANGUAGE PolyKinds #-} 4 | {-# LANGUAGE QuantifiedConstraints #-} 5 | -- Needed because the CPSed versions of Writer and State are secretly State 6 | -- wrappers, which don't force such constraints, even though they should legally 7 | -- be there. 8 | {-# OPTIONS_GHC -Wno-redundant-constraints #-} 9 | 10 | {- | 11 | Module : Control.Monad.Cont.Class 12 | Copyright : (c) The University of Glasgow 2001, 13 | (c) Jeff Newbern 2003-2007, 14 | (c) Andriy Palamarchuk 2007 15 | License : BSD-style (see the file LICENSE) 16 | 17 | Maintainer : libraries@haskell.org 18 | Stability : experimental 19 | Portability : portable 20 | 21 | [Computation type:] Computations which can be interrupted and resumed. 22 | 23 | [Binding strategy:] Binding a function to a monadic value creates 24 | a new continuation which uses the function as the continuation of the monadic 25 | computation. 26 | 27 | [Useful for:] Complex control structures, error handling, 28 | and creating co-routines. 29 | 30 | [Zero and plus:] None. 31 | 32 | [Example type:] @'Cont' r a@ 33 | 34 | The Continuation monad represents computations in continuation-passing style 35 | (CPS). 36 | In continuation-passing style function result is not returned, 37 | but instead is passed to another function, 38 | received as a parameter (continuation). 39 | Computations are built up from sequences 40 | of nested continuations, terminated by a final continuation (often @id@) 41 | which produces the final result. 42 | Since continuations are functions which represent the future of a computation, 43 | manipulation of the continuation functions can achieve complex manipulations 44 | of the future of the computation, 45 | such as interrupting a computation in the middle, aborting a portion 46 | of a computation, restarting a computation, and interleaving execution of 47 | computations. 48 | The Continuation monad adapts CPS to the structure of a monad. 49 | 50 | Before using the Continuation monad, be sure that you have 51 | a firm understanding of continuation-passing style 52 | and that continuations represent the best solution to your particular 53 | design problem. 54 | Many algorithms which require continuations in other languages do not require 55 | them in Haskell, due to Haskell's lazy semantics. 56 | Abuse of the Continuation monad can produce code that is impossible 57 | to understand and maintain. 58 | -} 59 | 60 | module Control.Monad.Cont.Class ( 61 | MonadCont(..), 62 | label, 63 | label_, 64 | liftCallCC, 65 | ) where 66 | 67 | import Data.Kind (Type) 68 | import Control.Monad.Fix (fix) 69 | import Control.Monad.Trans.Cont (ContT) 70 | import qualified Control.Monad.Trans.Cont as ContT 71 | import Control.Monad.Trans.Except (ExceptT) 72 | import qualified Control.Monad.Trans.Except as Except 73 | import Control.Monad.Trans.Identity (IdentityT) 74 | import qualified Control.Monad.Trans.Identity as Identity 75 | import Control.Monad.Trans.Maybe (MaybeT) 76 | import qualified Control.Monad.Trans.Maybe as Maybe 77 | import Control.Monad.Trans.Reader (ReaderT) 78 | import qualified Control.Monad.Trans.Reader as Reader 79 | import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS 80 | import qualified Control.Monad.Trans.RWS.Strict as StrictRWS 81 | import qualified Control.Monad.Trans.State.Lazy as LazyState 82 | import qualified Control.Monad.Trans.State.Strict as StrictState 83 | import qualified Control.Monad.Trans.Writer.Lazy as LazyWriter 84 | import qualified Control.Monad.Trans.Writer.Strict as StrictWriter 85 | import Control.Monad.Trans.Accum (AccumT) 86 | import qualified Control.Monad.Trans.Accum as Accum 87 | import qualified Control.Monad.Trans.RWS.CPS as CPSRWS 88 | import qualified Control.Monad.Trans.Writer.CPS as CPSWriter 89 | import Control.Monad.Trans.Class (MonadTrans (lift)) 90 | import Control.Monad.Signatures (CallCC) 91 | import Control.Monad (join) 92 | 93 | class Monad m => MonadCont (m :: Type -> Type) where 94 | {- | @callCC@ (call-with-current-continuation) 95 | calls a function with the current continuation as its argument. 96 | Provides an escape continuation mechanism for use with Continuation monads. 97 | Escape continuations allow to abort the current computation and return 98 | a value immediately. 99 | They achieve a similar effect to 'Control.Monad.Error.Class.throwError' 100 | and 'Control.Monad.Error.Class.catchError' 101 | within an 'Control.Monad.Except.Except' monad. 102 | Advantage of this function over calling @return@ is that it makes 103 | the continuation explicit, 104 | allowing more flexibility and better control 105 | (see examples in "Control.Monad.Cont"). 106 | 107 | The standard idiom used with @callCC@ is to provide a lambda-expression 108 | to name the continuation. Then calling the named continuation anywhere 109 | within its scope will escape from the computation, 110 | even if it is many layers deep within nested computations. 111 | -} 112 | callCC :: ((a -> m b) -> m a) -> m a 113 | {-# MINIMAL callCC #-} 114 | 115 | -- | @since 2.3.1 116 | instance forall k (r :: k) (m :: (k -> Type)) . MonadCont (ContT r m) where 117 | callCC = ContT.callCC 118 | 119 | -- --------------------------------------------------------------------------- 120 | -- Instances for other mtl transformers 121 | 122 | -- | @since 2.2 123 | instance MonadCont m => MonadCont (ExceptT e m) where 124 | callCC = Except.liftCallCC callCC 125 | 126 | instance MonadCont m => MonadCont (IdentityT m) where 127 | callCC = Identity.liftCallCC callCC 128 | 129 | instance MonadCont m => MonadCont (MaybeT m) where 130 | callCC = Maybe.liftCallCC callCC 131 | 132 | instance MonadCont m => MonadCont (ReaderT r m) where 133 | callCC = Reader.liftCallCC callCC 134 | 135 | instance (Monoid w, MonadCont m) => MonadCont (LazyRWS.RWST r w s m) where 136 | callCC = LazyRWS.liftCallCC' callCC 137 | 138 | instance (Monoid w, MonadCont m) => MonadCont (StrictRWS.RWST r w s m) where 139 | callCC = StrictRWS.liftCallCC' callCC 140 | 141 | instance MonadCont m => MonadCont (LazyState.StateT s m) where 142 | callCC = LazyState.liftCallCC' callCC 143 | 144 | instance MonadCont m => MonadCont (StrictState.StateT s m) where 145 | callCC = StrictState.liftCallCC' callCC 146 | 147 | instance (Monoid w, MonadCont m) => MonadCont (LazyWriter.WriterT w m) where 148 | callCC = LazyWriter.liftCallCC callCC 149 | 150 | instance (Monoid w, MonadCont m) => MonadCont (StrictWriter.WriterT w m) where 151 | callCC = StrictWriter.liftCallCC callCC 152 | 153 | -- | @since 2.3 154 | instance (Monoid w, MonadCont m) => MonadCont (CPSRWS.RWST r w s m) where 155 | callCC = CPSRWS.liftCallCC' callCC 156 | 157 | -- | @since 2.3 158 | instance (Monoid w, MonadCont m) => MonadCont (CPSWriter.WriterT w m) where 159 | callCC = CPSWriter.liftCallCC callCC 160 | 161 | -- | @since 2.3 162 | instance 163 | ( Monoid w 164 | , MonadCont m 165 | ) => MonadCont (AccumT w m) where 166 | callCC = Accum.liftCallCC callCC 167 | 168 | -- | Introduces a recursive binding to the continuation. 169 | -- Due to the use of @callCC@, calling the continuation will interrupt execution 170 | -- of the current block creating an effect similar to goto/setjmp in C. 171 | -- 172 | -- @since 2.3.1 173 | -- 174 | label :: MonadCont m => a -> m (a -> m b, a) 175 | label a = callCC $ \k -> let go b = k (go, b) in return (go, a) 176 | 177 | -- | Simplified version of `label` without arguments. 178 | -- 179 | -- @since 2.3.1 180 | -- 181 | label_ :: MonadCont m => m (m a) 182 | label_ = callCC $ return . fix 183 | 184 | -- | Lift a 'ContT.callCC'-style function through any 'MonadTrans'. 185 | -- 186 | -- = Note 187 | -- 188 | -- For any function @f@, @'liftCallCC' f@ satisfies the [uniformity 189 | -- condition](https://hackage.haskell.org/package/transformers-0.5.6.2/docs/Control-Monad-Signatures.html#t:CallCC) 190 | -- provided that @f@ is quasi-algebraic. More specifically, for any @g@, we must have: 191 | -- 192 | -- @ 193 | -- 'join' '$' f (\exit -> 'pure' '$' g (exit '.' 'pure') = f g 194 | -- @ 195 | -- 196 | -- 'ContT.callCC' is quasi-algebraic; furthermore, for any quasi-algebraic @f@, 197 | -- @'liftCallCC' f@ is also quasi-algebraic. 198 | -- 199 | -- = See also 200 | -- 201 | -- * [Proof of quasi-algebraic 202 | -- properties](https://gist.github.com/KingoftheHomeless/5927257cc7f6f8a2da685a2045dac204) 203 | -- * [Original issue](https://github.com/haskell/mtl/issues/77) 204 | -- 205 | -- @since 2.3.1 206 | liftCallCC :: 207 | forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) (a :: Type) (b :: Type) . 208 | (MonadTrans t, Monad m, forall (m' :: Type -> Type) . Monad m' => Monad (t m')) => 209 | CallCC m (t m a) b -> CallCC (t m) a b 210 | liftCallCC f g = join . lift . f $ \exit -> pure $ g (lift . exit . pure) 211 | -------------------------------------------------------------------------------- /Control/Monad/Error/Class.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleInstances #-} 2 | {-# LANGUAGE FunctionalDependencies #-} 3 | {-# LANGUAGE MultiParamTypeClasses #-} 4 | {-# LANGUAGE UndecidableInstances #-} 5 | {-# LANGUAGE Safe #-} 6 | -- Needed because the CPSed versions of Writer and State are secretly State 7 | -- wrappers, which don't force such constraints, even though they should legally 8 | -- be there. 9 | {-# OPTIONS_GHC -Wno-redundant-constraints #-} 10 | 11 | {- | 12 | Module : Control.Monad.Error.Class 13 | Copyright : (c) Michael Weber 2001, 14 | (c) Jeff Newbern 2003-2006, 15 | (c) Andriy Palamarchuk 2006 16 | (c) Edward Kmett 2012 17 | License : BSD-style (see the file LICENSE) 18 | 19 | Maintainer : libraries@haskell.org 20 | Stability : experimental 21 | Portability : non-portable (multi-parameter type classes) 22 | 23 | [Computation type:] Computations which may fail or throw exceptions. 24 | 25 | [Binding strategy:] Failure records information about the cause\/location 26 | of the failure. Failure values bypass the bound function, 27 | other values are used as inputs to the bound function. 28 | 29 | [Useful for:] Building computations from sequences of functions that may fail 30 | or using exception handling to structure error handling. 31 | 32 | [Zero and plus:] Zero is represented by an empty error and the plus operation 33 | executes its second argument if the first fails. 34 | 35 | [Example type:] @'Either' 'String' a@ 36 | 37 | The Error monad (also called the Exception monad). 38 | -} 39 | 40 | {- 41 | Rendered by Michael Weber , 42 | inspired by the Haskell Monad Template Library from 43 | Andy Gill () 44 | -} 45 | module Control.Monad.Error.Class ( 46 | MonadError(..), 47 | liftEither, 48 | tryError, 49 | withError, 50 | handleError, 51 | mapError, 52 | modifyError, 53 | ) where 54 | 55 | import Control.Monad.Trans.Except (ExceptT) 56 | import qualified Control.Monad.Trans.Except as ExceptT (catchE, runExceptT, throwE) 57 | import Control.Monad.Trans.Identity (IdentityT) 58 | import qualified Control.Monad.Trans.Identity as Identity 59 | import Control.Monad.Trans.Maybe (MaybeT) 60 | import qualified Control.Monad.Trans.Maybe as Maybe 61 | import Control.Monad.Trans.Reader (ReaderT) 62 | import qualified Control.Monad.Trans.Reader as Reader 63 | import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS 64 | import qualified Control.Monad.Trans.RWS.Strict as StrictRWS 65 | import qualified Control.Monad.Trans.State.Lazy as LazyState 66 | import qualified Control.Monad.Trans.State.Strict as StrictState 67 | import qualified Control.Monad.Trans.Writer.Lazy as LazyWriter 68 | import qualified Control.Monad.Trans.Writer.Strict as StrictWriter 69 | import Control.Monad.Trans.Accum (AccumT) 70 | import qualified Control.Monad.Trans.Accum as Accum 71 | import qualified Control.Monad.Trans.RWS.CPS as CPSRWS 72 | import qualified Control.Monad.Trans.Writer.CPS as CPSWriter 73 | import Control.Monad.Trans.Class (lift) 74 | import Control.Exception (IOException, catch, ioError) 75 | import Control.Monad (Monad) 76 | import Data.Monoid (Monoid) 77 | import Prelude (Either (Left, Right), Maybe (Nothing), either, flip, (.), IO, pure, (<$>), (>>=)) 78 | 79 | {- | 80 | The strategy of combining computations that can throw exceptions 81 | by bypassing bound functions 82 | from the point an exception is thrown to the point that it is handled. 83 | 84 | Is parameterized over the type of error information and 85 | the monad type constructor. 86 | It is common to use @'Either' String@ as the monad type constructor 87 | for an error monad in which error descriptions take the form of strings. 88 | In that case and many other common cases the resulting monad is already defined 89 | as an instance of the 'MonadError' class. 90 | You can also define your own error type and\/or use a monad type constructor 91 | other than @'Either' 'String'@ or @'Either' 'IOError'@. 92 | In these cases you will have to explicitly define instances of the 'MonadError' 93 | class. 94 | (If you are using the deprecated "Control.Monad.Error" or 95 | "Control.Monad.Trans.Error", you may also have to define an 'Error' instance.) 96 | -} 97 | class (Monad m) => MonadError e m | m -> e where 98 | -- | Is used within a monadic computation to begin exception processing. 99 | throwError :: e -> m a 100 | 101 | {- | 102 | A handler function to handle previous errors and return to normal execution. 103 | A common idiom is: 104 | 105 | > do { action1; action2; action3 } `catchError` handler 106 | 107 | where the @action@ functions can call 'throwError'. 108 | Note that @handler@ and the do-block must have the same return type. 109 | -} 110 | catchError :: m a -> (e -> m a) -> m a 111 | {-# MINIMAL throwError, catchError #-} 112 | 113 | {- | 114 | Lifts an @'Either' e@ into any @'MonadError' e@. 115 | 116 | > do { val <- liftEither =<< action1; action2 } 117 | 118 | where @action1@ returns an 'Either' to represent errors. 119 | 120 | @since 2.2.2 121 | -} 122 | liftEither :: MonadError e m => Either e a -> m a 123 | liftEither = either throwError pure 124 | 125 | instance MonadError IOException IO where 126 | throwError = ioError 127 | catchError = catch 128 | 129 | {- | @since 2.2.2 -} 130 | instance MonadError () Maybe where 131 | throwError () = Nothing 132 | catchError Nothing f = f () 133 | catchError x _ = x 134 | 135 | -- --------------------------------------------------------------------------- 136 | -- Our parameterizable error monad 137 | 138 | instance MonadError e (Either e) where 139 | throwError = Left 140 | Left l `catchError` h = h l 141 | Right r `catchError` _ = Right r 142 | 143 | {- | @since 2.2 -} 144 | instance Monad m => MonadError e (ExceptT e m) where 145 | throwError = ExceptT.throwE 146 | catchError = ExceptT.catchE 147 | 148 | -- --------------------------------------------------------------------------- 149 | -- Instances for other mtl transformers 150 | -- 151 | -- All of these instances need UndecidableInstances, 152 | -- because they do not satisfy the coverage condition. 153 | 154 | instance MonadError e m => MonadError e (IdentityT m) where 155 | throwError = lift . throwError 156 | catchError = Identity.liftCatch catchError 157 | 158 | instance MonadError e m => MonadError e (MaybeT m) where 159 | throwError = lift . throwError 160 | catchError = Maybe.liftCatch catchError 161 | 162 | instance MonadError e m => MonadError e (ReaderT r m) where 163 | throwError = lift . throwError 164 | catchError = Reader.liftCatch catchError 165 | 166 | instance (Monoid w, MonadError e m) => MonadError e (LazyRWS.RWST r w s m) where 167 | throwError = lift . throwError 168 | catchError = LazyRWS.liftCatch catchError 169 | 170 | instance (Monoid w, MonadError e m) => MonadError e (StrictRWS.RWST r w s m) where 171 | throwError = lift . throwError 172 | catchError = StrictRWS.liftCatch catchError 173 | 174 | instance MonadError e m => MonadError e (LazyState.StateT s m) where 175 | throwError = lift . throwError 176 | catchError = LazyState.liftCatch catchError 177 | 178 | instance MonadError e m => MonadError e (StrictState.StateT s m) where 179 | throwError = lift . throwError 180 | catchError = StrictState.liftCatch catchError 181 | 182 | instance (Monoid w, MonadError e m) => MonadError e (LazyWriter.WriterT w m) where 183 | throwError = lift . throwError 184 | catchError = LazyWriter.liftCatch catchError 185 | 186 | instance (Monoid w, MonadError e m) => MonadError e (StrictWriter.WriterT w m) where 187 | throwError = lift . throwError 188 | catchError = StrictWriter.liftCatch catchError 189 | 190 | -- | @since 2.3 191 | instance (Monoid w, MonadError e m) => MonadError e (CPSRWS.RWST r w s m) where 192 | throwError = lift . throwError 193 | catchError = CPSRWS.liftCatch catchError 194 | 195 | -- | @since 2.3 196 | instance (Monoid w, MonadError e m) => MonadError e (CPSWriter.WriterT w m) where 197 | throwError = lift . throwError 198 | catchError = CPSWriter.liftCatch catchError 199 | 200 | -- | @since 2.3 201 | instance 202 | ( Monoid w 203 | , MonadError e m 204 | ) => MonadError e (AccumT w m) where 205 | throwError = lift . throwError 206 | catchError = Accum.liftCatch catchError 207 | 208 | -- | 'MonadError' analogue to the 'Control.Exception.try' function. 209 | -- 210 | -- @since 2.3 211 | tryError :: MonadError e m => m a -> m (Either e a) 212 | tryError action = (Right <$> action) `catchError` (pure . Left) 213 | 214 | -- | 'MonadError' analogue to the 'withExceptT' function. 215 | -- Modify the value (but not the type) of an error. The type is 216 | -- fixed because of the functional dependency @m -> e@. If you need 217 | -- to change the type of @e@ use 'mapError' or 'modifyError'. 218 | -- 219 | -- @since 2.3 220 | withError :: MonadError e m => (e -> e) -> m a -> m a 221 | withError f action = tryError action >>= either (throwError . f) pure 222 | 223 | -- | As 'handle' is flipped 'Control.Exception.catch', 'handleError' 224 | -- is flipped 'catchError'. 225 | -- 226 | -- @since 2.3 227 | handleError :: MonadError e m => (e -> m a) -> m a -> m a 228 | handleError = flip catchError 229 | 230 | -- | 'MonadError' analogue of the 'mapExceptT' function. The 231 | -- computation is unwrapped, a function is applied to the @Either@, and 232 | -- the result is lifted into the second 'MonadError' instance. 233 | -- 234 | -- @since 2.3 235 | mapError :: (MonadError e m, MonadError e' n) => (m (Either e a) -> n (Either e' b)) -> m a -> n b 236 | mapError f action = f (tryError action) >>= liftEither 237 | 238 | {- | 239 | A different 'MonadError' analogue to the 'withExceptT' function. 240 | Modify the value (and possibly the type) of an error in an @ExceptT@-transformed 241 | monad, while stripping the @ExceptT@ layer. 242 | 243 | This is useful for adapting the 'MonadError' constraint of a computation. 244 | 245 | For example: 246 | 247 | > data DatabaseError = ... 248 | > 249 | > performDatabaseQuery :: (MonadError DatabaseError m, ...) => m PersistedValue 250 | > 251 | > data AppError 252 | > = MkDatabaseError DatabaseError 253 | > | ... 254 | > 255 | > app :: (MonadError AppError m, ...) => m () 256 | 257 | Given these types, @performDatabaseQuery@ cannot be used directly inside 258 | @app@, because the error types don't match. Using 'modifyError', an equivalent 259 | function with a different error type can be constructed: 260 | 261 | > performDatabaseQuery' :: (MonadError AppError m, ...) => m PersistedValue 262 | > performDatabaseQuery' = modifyError MkDatabaseError performDatabaseQuery 263 | 264 | Since the error types do match, @performDatabaseQuery'@ _can_ be used in @app@, 265 | assuming all other constraints carry over. 266 | 267 | This works by instantiating the @m@ in the type of @performDatabaseQuery@ to 268 | @ExceptT DatabaseError m'@, which satisfies the @MonadError DatabaseError@ 269 | constraint. Immediately, the @ExceptT DatabaseError@ layer is unwrapped, 270 | producing 'Either' a @DatabaseError@ or a @PersistedValue@. If it's the former, 271 | the error is wrapped in @MkDatabaseError@ and re-thrown in the inner monad, 272 | otherwise the result value is returned. 273 | 274 | @since 2.3.1 275 | -} 276 | modifyError :: MonadError e' m => (e -> e') -> ExceptT e m a -> m a 277 | modifyError f m = ExceptT.runExceptT m >>= either (throwError . f) pure 278 | -------------------------------------------------------------------------------- /Control/Monad/Except.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | {- | 3 | Module : Control.Monad.Except 4 | Copyright : (c) Michael Weber 2001, 5 | (c) Jeff Newbern 2003-2006, 6 | (c) Andriy Palamarchuk 2006 7 | License : BSD-style (see the file LICENSE) 8 | 9 | Maintainer : libraries@haskell.org 10 | Stability : experimental 11 | Portability : non-portable (multi-parameter type classes) 12 | 13 | [Computation type:] Computations which may fail or throw exceptions. 14 | 15 | [Binding strategy:] Failure records information about the cause\/location 16 | of the failure. Failure values bypass the bound function, 17 | other values are used as inputs to the bound function. 18 | 19 | [Useful for:] Building computations from sequences of functions that may fail 20 | or using exception handling to structure error handling. 21 | 22 | [Example type:] @'Either' String a@ 23 | 24 | The Error monad (also called the Exception monad). 25 | 26 | @since 2.2.1 27 | -} 28 | 29 | {- 30 | Rendered by Michael Weber , 31 | inspired by the Haskell Monad Template Library from 32 | Andy Gill () 33 | -} 34 | module Control.Monad.Except 35 | ( 36 | -- * Warning 37 | -- $warning 38 | -- * Monads with error handling 39 | Error.MonadError(..), 40 | Error.liftEither, 41 | Error.tryError, 42 | Error.withError, 43 | Error.handleError, 44 | Error.mapError, 45 | Error.modifyError, 46 | -- * The ExceptT monad transformer 47 | Except.ExceptT(ExceptT), 48 | Except.Except, 49 | Except.runExceptT, 50 | Except.mapExceptT, 51 | Except.withExceptT, 52 | Except.runExcept, 53 | Except.mapExcept, 54 | Except.withExcept, 55 | -- * Example 1: Custom Error Data Type 56 | -- $customErrorExample 57 | 58 | -- * Example 2: Using ExceptT Monad Transformer 59 | -- $ExceptTExample 60 | ) where 61 | 62 | import qualified Control.Monad.Error.Class as Error 63 | import qualified Control.Monad.Trans.Except as Except 64 | 65 | {- $warning 66 | Please do not confuse 'ExceptT' and 'throwError' with 'Control.Exception.Exception' / 67 | 'Control.Exception.SomeException' and 'Control.Exception.catch', respectively. The latter 68 | are for exceptions built into GHC, by default, and are mostly used from within the IO monad. 69 | They do not interact with the \"exceptions\" in this package at all. This package allows you 70 | to define a new kind of exception control mechanism which does not necessarily need your code to 71 | be placed in the IO monad. 72 | 73 | In short, all \"catching\" mechanisms in this library will be unable to catch exceptions thrown 74 | by functions in the "Control.Exception" module, and vice-versa. 75 | -} 76 | 77 | {- $customErrorExample 78 | Here is an example that demonstrates the use of a custom error data type with 79 | the 'throwError' and 'catchError' exception mechanism from 'MonadError'. 80 | The example throws an exception if the user enters an empty string 81 | or a string longer than 5 characters. Otherwise it prints length of the string. 82 | 83 | >-- This is the type to represent length calculation error. 84 | >data LengthError = EmptyString -- Entered string was empty. 85 | > | StringTooLong Int -- A string is longer than 5 characters. 86 | > -- Records a length of the string. 87 | > | OtherError String -- Other error, stores the problem description. 88 | > 89 | >-- Converts LengthError to a readable message. 90 | >instance Show LengthError where 91 | > show EmptyString = "The string was empty!" 92 | > show (StringTooLong len) = 93 | > "The length of the string (" ++ (show len) ++ ") is bigger than 5!" 94 | > show (OtherError msg) = msg 95 | > 96 | >-- For our monad type constructor, we use Either LengthError 97 | >-- which represents failure using Left LengthError 98 | >-- or a successful result of type a using Right a. 99 | >type LengthMonad = Either LengthError 100 | > 101 | >main = do 102 | > putStrLn "Please enter a string:" 103 | > s <- getLine 104 | > reportResult (calculateLength s) 105 | > 106 | >-- Attempts to calculate length and throws an error if the provided string is 107 | >-- empty or longer than 5 characters. 108 | >-- (Throwing an error in this monad means returning a 'Left'.) 109 | >calculateLength :: String -> LengthMonad Int 110 | >calculateLength [] = throwError EmptyString 111 | >calculateLength s | len > 5 = throwError (StringTooLong len) 112 | > | otherwise = return len 113 | > where len = length s 114 | > 115 | >-- Prints result of the string length calculation. 116 | >reportResult :: LengthMonad Int -> IO () 117 | >reportResult (Right len) = putStrLn ("The length of the string is " ++ (show len)) 118 | >reportResult (Left e) = putStrLn ("Length calculation failed with error: " ++ (show e)) 119 | -} 120 | 121 | {- $ExceptTExample 122 | @'ExceptT'@ monad transformer can be used to add error handling to another monad. 123 | Here is an example how to combine it with an @IO@ monad: 124 | 125 | >import Control.Monad.Except 126 | > 127 | >-- An IO monad which can return String failure. 128 | >-- It is convenient to define the monad type of the combined monad, 129 | >-- especially if we combine more monad transformers. 130 | >type LengthMonad = ExceptT String IO 131 | > 132 | >main = do 133 | > -- runExceptT removes the ExceptT wrapper 134 | > r <- runExceptT calculateLength 135 | > reportResult r 136 | > 137 | >-- Asks user for a non-empty string and returns its length. 138 | >-- Throws an error if user enters an empty string. 139 | >calculateLength :: LengthMonad Int 140 | >calculateLength = do 141 | > -- all the IO operations have to be lifted to the IO monad in the monad stack 142 | > liftIO $ putStrLn "Please enter a non-empty string: " 143 | > s <- liftIO getLine 144 | > if null s 145 | > then throwError "The string was empty!" 146 | > else return $ length s 147 | > 148 | >-- Prints result of the string length calculation. 149 | >reportResult :: Either String Int -> IO () 150 | >reportResult (Right len) = putStrLn ("The length of the string is " ++ (show len)) 151 | >reportResult (Left e) = putStrLn ("Length calculation failed with error: " ++ (show e)) 152 | -} 153 | -------------------------------------------------------------------------------- /Control/Monad/Identity.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | {- | 3 | Module : Control.Monad.Identity 4 | Copyright : (c) Andy Gill 2001, 5 | (c) Oregon Graduate Institute of Science and Technology 2001, 6 | (c) Jeff Newbern 2003-2006, 7 | (c) Andriy Palamarchuk 2006 8 | License : BSD-style (see the file LICENSE) 9 | 10 | Maintainer : libraries@haskell.org 11 | Stability : experimental 12 | Portability : portable 13 | 14 | [Computation type:] Simple function application. 15 | 16 | [Binding strategy:] The bound function is applied to the input value. 17 | @'Identity' x >>= f == f x@ 18 | 19 | [Useful for:] Monads can be derived from monad transformers applied to the 20 | 'Identity' monad. 21 | 22 | [Zero and plus:] None. 23 | 24 | [Example type:] @'Identity' a@ 25 | 26 | The @Identity@ monad is a monad that does not embody any computational strategy. 27 | It simply applies the bound function to its input without any modification. 28 | Computationally, there is no reason to use the @Identity@ monad 29 | instead of the much simpler act of simply applying functions to their arguments. 30 | The purpose of the @Identity@ monad is its fundamental role in the theory 31 | of monad transformers. 32 | Any monad transformer applied to the @Identity@ monad yields a non-transformer 33 | version of that monad. 34 | -} 35 | 36 | module Control.Monad.Identity ( 37 | module Data.Functor.Identity, 38 | module Control.Monad.Trans.Identity, 39 | ) where 40 | 41 | import Data.Functor.Identity 42 | import Control.Monad.Trans.Identity 43 | -------------------------------------------------------------------------------- /Control/Monad/RWS.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | ----------------------------------------------------------------------------- 4 | -- | 5 | -- Module : Control.Monad.RWS 6 | -- Copyright : (c) Andy Gill 2001, 7 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 8 | -- License : BSD-style (see the file LICENSE) 9 | -- 10 | -- Maintainer : libraries@haskell.org 11 | -- Stability : experimental 12 | -- Portability : non-portable (multi-param classes, functional dependencies) 13 | -- 14 | -- Declaration of the MonadRWS class. 15 | -- 16 | -- Inspired by the paper 17 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 18 | -- Mark P Jones () 19 | -- Advanced School of Functional Programming, 1995. 20 | ----------------------------------------------------------------------------- 21 | 22 | module Control.Monad.RWS ( 23 | module Control.Monad.RWS.Lazy 24 | ) where 25 | 26 | import Control.Monad.RWS.Lazy 27 | -------------------------------------------------------------------------------- /Control/Monad/RWS/CPS.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | ----------------------------------------------------------------------------- 3 | -- | 4 | -- Module : Control.Monad.RWS.Strict 5 | -- Copyright : (c) Andy Gill 2001, 6 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 7 | -- License : BSD-style (see the file LICENSE) 8 | -- 9 | -- Maintainer : libraries@haskell.org 10 | -- Stability : experimental 11 | -- Portability : non-portable (multi-param classes, functional dependencies) 12 | -- 13 | -- Strict RWS monad that uses continuation-passing-style to achieve constant 14 | -- space usage. 15 | -- 16 | -- Inspired by the paper 17 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 18 | -- Mark P Jones () 19 | -- Advanced School of Functional Programming, 1995. 20 | -- 21 | -- /Since: mtl-2.3, transformers-0.5.6/ 22 | ----------------------------------------------------------------------------- 23 | 24 | module Control.Monad.RWS.CPS ( 25 | -- * The RWS monad 26 | RWS, 27 | rws, 28 | runRWS, 29 | evalRWS, 30 | execRWS, 31 | mapRWS, 32 | withRWS, 33 | -- * The RWST monad transformer 34 | RWST, 35 | runRWST, 36 | evalRWST, 37 | execRWST, 38 | mapRWST, 39 | withRWST, 40 | -- * Strict Reader-writer-state monads 41 | module Control.Monad.RWS.Class, 42 | module Control.Monad.Trans, 43 | ) where 44 | 45 | import Control.Monad.RWS.Class 46 | 47 | import Control.Monad.Trans 48 | import Control.Monad.Trans.RWS.CPS ( 49 | RWS, rws, runRWS, evalRWS, execRWS, mapRWS, withRWS, 50 | RWST, runRWST, evalRWST, execRWST, mapRWST, withRWST) 51 | -------------------------------------------------------------------------------- /Control/Monad/RWS/Class.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleInstances #-} 2 | {-# LANGUAGE FunctionalDependencies #-} 3 | {-# LANGUAGE MultiParamTypeClasses #-} 4 | -- Search for UndecidableInstances to see why this is needed 5 | {-# LANGUAGE UndecidableInstances #-} 6 | {-# LANGUAGE Safe #-} 7 | 8 | ----------------------------------------------------------------------------- 9 | -- | 10 | -- Module : Control.Monad.RWS.Class 11 | -- Copyright : (c) Andy Gill 2001, 12 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 13 | -- License : BSD-style (see the file LICENSE) 14 | -- 15 | -- Maintainer : libraries@haskell.org 16 | -- Stability : experimental 17 | -- Portability : non-portable (multi-param classes, functional dependencies) 18 | -- 19 | -- Declaration of the MonadRWS class. 20 | -- 21 | -- Inspired by the paper 22 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 23 | -- Mark P Jones () 24 | -- Advanced School of Functional Programming, 1995. 25 | ----------------------------------------------------------------------------- 26 | 27 | module Control.Monad.RWS.Class ( 28 | MonadRWS, 29 | module Control.Monad.Reader.Class, 30 | module Control.Monad.State.Class, 31 | module Control.Monad.Writer.Class, 32 | ) where 33 | 34 | import Control.Monad.Reader.Class 35 | import Control.Monad.State.Class 36 | import Control.Monad.Writer.Class 37 | 38 | import Control.Monad.Trans.Except (ExceptT) 39 | import Control.Monad.Trans.Maybe (MaybeT) 40 | import Control.Monad.Trans.Identity (IdentityT) 41 | import qualified Control.Monad.Trans.RWS.CPS as CPS (RWST) 42 | import qualified Control.Monad.Trans.RWS.Lazy as Lazy (RWST) 43 | import qualified Control.Monad.Trans.RWS.Strict as Strict (RWST) 44 | 45 | class (Monoid w, MonadReader r m, MonadWriter w m, MonadState s m) 46 | => MonadRWS r w s m | m -> r, m -> w, m -> s 47 | 48 | -- | @since 2.3 49 | instance (Monoid w, Monad m) => MonadRWS r w s (CPS.RWST r w s m) 50 | 51 | instance (Monoid w, Monad m) => MonadRWS r w s (Lazy.RWST r w s m) 52 | 53 | instance (Monoid w, Monad m) => MonadRWS r w s (Strict.RWST r w s m) 54 | 55 | --------------------------------------------------------------------------- 56 | -- Instances for other mtl transformers 57 | -- 58 | -- All of these instances need UndecidableInstances, 59 | -- because they do not satisfy the coverage condition. 60 | 61 | -- | @since 2.2 62 | instance MonadRWS r w s m => MonadRWS r w s (ExceptT e m) 63 | instance MonadRWS r w s m => MonadRWS r w s (IdentityT m) 64 | instance MonadRWS r w s m => MonadRWS r w s (MaybeT m) 65 | -------------------------------------------------------------------------------- /Control/Monad/RWS/Lazy.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | ----------------------------------------------------------------------------- 3 | -- | 4 | -- Module : Control.Monad.RWS.Lazy 5 | -- Copyright : (c) Andy Gill 2001, 6 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 7 | -- License : BSD-style (see the file LICENSE) 8 | -- 9 | -- Maintainer : libraries@haskell.org 10 | -- Stability : experimental 11 | -- Portability : non-portable (multi-param classes, functional dependencies) 12 | -- 13 | -- Lazy RWS monad. 14 | -- 15 | -- Inspired by the paper 16 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 17 | -- Mark P Jones () 18 | -- Advanced School of Functional Programming, 1995. 19 | ----------------------------------------------------------------------------- 20 | 21 | module Control.Monad.RWS.Lazy ( 22 | -- * The RWS monad 23 | RWS, 24 | rws, 25 | runRWS, 26 | evalRWS, 27 | execRWS, 28 | mapRWS, 29 | withRWS, 30 | -- * The RWST monad transformer 31 | RWST(RWST), 32 | runRWST, 33 | evalRWST, 34 | execRWST, 35 | mapRWST, 36 | withRWST, 37 | -- * Lazy Reader-writer-state monads 38 | module Control.Monad.RWS.Class, 39 | module Control.Monad.Trans, 40 | ) where 41 | 42 | import Control.Monad.RWS.Class 43 | 44 | import Control.Monad.Trans 45 | import Control.Monad.Trans.RWS.Lazy ( 46 | RWS, rws, runRWS, evalRWS, execRWS, mapRWS, withRWS, 47 | RWST(RWST), runRWST, evalRWST, execRWST, mapRWST, withRWST) 48 | -------------------------------------------------------------------------------- /Control/Monad/RWS/Strict.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | ----------------------------------------------------------------------------- 3 | -- | 4 | -- Module : Control.Monad.RWS.Strict 5 | -- Copyright : (c) Andy Gill 2001, 6 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 7 | -- License : BSD-style (see the file LICENSE) 8 | -- 9 | -- Maintainer : libraries@haskell.org 10 | -- Stability : experimental 11 | -- Portability : non-portable (multi-param classes, functional dependencies) 12 | -- 13 | -- Strict RWS monad. 14 | -- 15 | -- Inspired by the paper 16 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 17 | -- Mark P Jones () 18 | -- Advanced School of Functional Programming, 1995. 19 | ----------------------------------------------------------------------------- 20 | 21 | module Control.Monad.RWS.Strict ( 22 | -- * The RWS monad 23 | RWS, 24 | rws, 25 | runRWS, 26 | evalRWS, 27 | execRWS, 28 | mapRWS, 29 | withRWS, 30 | -- * The RWST monad transformer 31 | RWST(RWST), 32 | runRWST, 33 | evalRWST, 34 | execRWST, 35 | mapRWST, 36 | withRWST, 37 | -- * Strict Reader-writer-state monads 38 | module Control.Monad.RWS.Class, 39 | module Control.Monad.Trans, 40 | ) where 41 | 42 | import Control.Monad.RWS.Class 43 | import Control.Monad.Trans 44 | 45 | import Control.Monad.Trans.RWS.Strict ( 46 | RWS, rws, runRWS, evalRWS, execRWS, mapRWS, withRWS, 47 | RWST(RWST), runRWST, evalRWST, execRWST, mapRWST, withRWST) 48 | -------------------------------------------------------------------------------- /Control/Monad/Reader.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | {- | 3 | Module : Control.Monad.Reader 4 | Copyright : (c) Andy Gill 2001, 5 | (c) Oregon Graduate Institute of Science and Technology 2001, 6 | (c) Jeff Newbern 2003-2007, 7 | (c) Andriy Palamarchuk 2007 8 | License : BSD-style (see the file LICENSE) 9 | 10 | Maintainer : libraries@haskell.org 11 | Stability : experimental 12 | Portability : non-portable (multi-param classes, functional dependencies) 13 | 14 | [Computation type:] Computations which read values from a shared environment. 15 | 16 | [Binding strategy:] Monad values are functions from the environment to a value. 17 | The bound function is applied to the bound value, and both have access 18 | to the shared environment. 19 | 20 | [Useful for:] Maintaining variable bindings, or other shared environment. 21 | 22 | [Zero and plus:] None. 23 | 24 | [Example type:] @'Reader' [(String,Value)] a@ 25 | 26 | The 'Reader' monad (also called the Environment monad). 27 | Represents a computation, which can read values from 28 | a shared environment, pass values from function to function, 29 | and execute sub-computations in a modified environment. 30 | Using 'Reader' monad for such computations is often clearer and easier 31 | than using the 'Control.Monad.State.State' monad. 32 | 33 | Inspired by the paper 34 | /Functional Programming with Overloading and Higher-Order Polymorphism/, 35 | Mark P Jones () 36 | Advanced School of Functional Programming, 1995. 37 | -} 38 | 39 | module Control.Monad.Reader ( 40 | -- * MonadReader class 41 | MonadReader.MonadReader(..), 42 | MonadReader.asks, 43 | -- * The Reader monad 44 | Reader, 45 | runReader, 46 | mapReader, 47 | withReader, 48 | -- * The ReaderT monad transformer 49 | ReaderT(ReaderT), 50 | runReaderT, 51 | mapReaderT, 52 | withReaderT, 53 | module Control.Monad.Trans, 54 | -- * Example 1: Simple Reader Usage 55 | -- $simpleReaderExample 56 | 57 | -- * Example 2: Modifying Reader Content With @local@ 58 | -- $localExample 59 | 60 | -- * Example 3: @ReaderT@ Monad Transformer 61 | -- $ReaderTExample 62 | ) where 63 | 64 | import qualified Control.Monad.Reader.Class as MonadReader 65 | import Control.Monad.Trans 66 | 67 | import Control.Monad.Trans.Reader ( 68 | Reader, runReader, mapReader, withReader, 69 | ReaderT(ReaderT), runReaderT, mapReaderT, withReaderT) 70 | 71 | {- $simpleReaderExample 72 | 73 | In this example the @Reader@ monad provides access to variable bindings. 74 | Bindings are a @Map@ of integer variables. 75 | The variable @count@ contains number of variables in the bindings. 76 | You can see how to run a Reader monad and retrieve data from it 77 | with 'runReader', how to access the Reader data with 'ask' and 'asks'. 78 | 79 | >import Control.Monad.Reader 80 | >import Data.Map (Map) 81 | >import qualified Data.Map as Map 82 | > 83 | >type Bindings = Map String Int 84 | > 85 | >-- Returns True if the "count" variable contains correct bindings size. 86 | >isCountCorrect :: Bindings -> Bool 87 | >isCountCorrect bindings = runReader calc_isCountCorrect bindings 88 | > 89 | >-- The Reader monad, which implements this complicated check. 90 | >calc_isCountCorrect :: Reader Bindings Bool 91 | >calc_isCountCorrect = do 92 | > count <- asks (lookupVar "count") 93 | > bindings <- ask 94 | > return (count == (Map.size bindings)) 95 | > 96 | >-- The selector function to use with 'asks'. 97 | >-- Returns value of the variable with specified name. 98 | >lookupVar :: String -> Bindings -> Int 99 | >lookupVar name bindings = maybe 0 id (Map.lookup name bindings) 100 | > 101 | >sampleBindings :: Bindings 102 | >sampleBindings = Map.fromList [("count", 3), ("1", 1), ("b", 2)] 103 | > 104 | >main :: IO () 105 | >main = do 106 | > putStr $ "Count is correct for bindings " ++ (show sampleBindings) ++ ": " 107 | > putStrLn $ show (isCountCorrect sampleBindings) 108 | -} 109 | 110 | {- $localExample 111 | 112 | Shows how to modify Reader content with 'local'. 113 | 114 | >import Control.Monad.Reader 115 | > 116 | >calculateContentLen :: Reader String Int 117 | >calculateContentLen = do 118 | > content <- ask 119 | > return (length content); 120 | > 121 | >-- Calls calculateContentLen after adding a prefix to the Reader content. 122 | >calculateModifiedContentLen :: Reader String Int 123 | >calculateModifiedContentLen = local ("Prefix " ++) calculateContentLen 124 | > 125 | >main :: IO () 126 | >main = do 127 | > let s = "12345"; 128 | > let modifiedLen = runReader calculateModifiedContentLen s 129 | > let len = runReader calculateContentLen s 130 | > putStrLn $ "Modified 's' length: " ++ (show modifiedLen) 131 | > putStrLn $ "Original 's' length: " ++ (show len) 132 | -} 133 | 134 | {- $ReaderTExample 135 | 136 | Now you are thinking: 'Wow, what a great monad! I wish I could use 137 | Reader functionality in MyFavoriteComplexMonad!'. Don't worry. 138 | This can be easily done with the 'ReaderT' monad transformer. 139 | This example shows how to combine @ReaderT@ with the IO monad. 140 | 141 | >import Control.Monad.Reader 142 | > 143 | >-- The Reader/IO combined monad, where Reader stores a string. 144 | >printReaderContent :: ReaderT String IO () 145 | >printReaderContent = do 146 | > content <- ask 147 | > liftIO $ putStrLn ("The Reader Content: " ++ content) 148 | > 149 | >main :: IO () 150 | >main = runReaderT printReaderContent "Some Content" 151 | -} 152 | -------------------------------------------------------------------------------- /Control/Monad/Reader/Class.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | {-# LANGUAGE FlexibleInstances #-} 3 | {-# LANGUAGE FunctionalDependencies #-} 4 | {-# LANGUAGE MultiParamTypeClasses #-} 5 | -- Search for UndecidableInstances to see why this is needed 6 | {-# LANGUAGE UndecidableInstances #-} 7 | -- Needed because the CPSed versions of Writer and State are secretly State 8 | -- wrappers, which don't force such constraints, even though they should legally 9 | -- be there. 10 | {-# OPTIONS_GHC -Wno-redundant-constraints #-} 11 | {- | 12 | Module : Control.Monad.Reader.Class 13 | Copyright : (c) Andy Gill 2001, 14 | (c) Oregon Graduate Institute of Science and Technology 2001, 15 | (c) Jeff Newbern 2003-2007, 16 | (c) Andriy Palamarchuk 2007 17 | License : BSD-style (see the file LICENSE) 18 | 19 | Maintainer : libraries@haskell.org 20 | Stability : experimental 21 | Portability : non-portable (multi-param classes, functional dependencies) 22 | 23 | [Computation type:] Computations which read values from a shared environment. 24 | 25 | [Binding strategy:] Monad values are functions from the environment to a value. 26 | The bound function is applied to the bound value, and both have access 27 | to the shared environment. 28 | 29 | [Useful for:] Maintaining variable bindings, or other shared environment. 30 | 31 | [Zero and plus:] None. 32 | 33 | [Example type:] @'Reader' [(String,Value)] a@ 34 | 35 | The 'Reader' monad (also called the Environment monad). 36 | Represents a computation, which can read values from 37 | a shared environment, pass values from function to function, 38 | and execute sub-computations in a modified environment. 39 | Using 'Reader' monad for such computations is often clearer and easier 40 | than using the 'Control.Monad.State.State' monad. 41 | 42 | Inspired by the paper 43 | /Functional Programming with Overloading and Higher-Order Polymorphism/, 44 | Mark P Jones () 45 | Advanced School of Functional Programming, 1995. 46 | -} 47 | 48 | module Control.Monad.Reader.Class ( 49 | MonadReader(..), 50 | asks, 51 | ) where 52 | 53 | import qualified Control.Monad.Trans.Cont as Cont 54 | import Control.Monad.Trans.Cont (ContT) 55 | import Control.Monad.Trans.Except (ExceptT, mapExceptT) 56 | import Control.Monad.Trans.Identity (IdentityT, mapIdentityT) 57 | import Control.Monad.Trans.Maybe (MaybeT, mapMaybeT) 58 | import Control.Monad.Trans.Reader (ReaderT) 59 | import qualified Control.Monad.Trans.Reader as ReaderT 60 | import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS 61 | import qualified Control.Monad.Trans.RWS.Strict as StrictRWS 62 | import qualified Control.Monad.Trans.State.Lazy as Lazy 63 | import qualified Control.Monad.Trans.State.Strict as Strict 64 | import qualified Control.Monad.Trans.Writer.Lazy as Lazy 65 | import qualified Control.Monad.Trans.Writer.Strict as Strict 66 | import Control.Monad.Trans.Accum (AccumT) 67 | import qualified Control.Monad.Trans.Accum as Accum 68 | import Control.Monad.Trans.Select (SelectT (SelectT), runSelectT) 69 | import qualified Control.Monad.Trans.RWS.CPS as CPSRWS 70 | import qualified Control.Monad.Trans.Writer.CPS as CPS 71 | import Control.Monad.Trans.Class (lift) 72 | 73 | -- ---------------------------------------------------------------------------- 74 | -- class MonadReader 75 | -- asks for the internal (non-mutable) state. 76 | 77 | -- | See examples in "Control.Monad.Reader". 78 | -- Note, the partially applied function type @(->) r@ is a simple reader monad. 79 | -- See the @instance@ declaration below. 80 | class Monad m => MonadReader r m | m -> r where 81 | {-# MINIMAL (ask | reader), local #-} 82 | -- | Retrieves the monad environment. 83 | ask :: m r 84 | ask = reader id 85 | 86 | -- | Executes a computation in a modified environment. 87 | local :: (r -> r) -- ^ The function to modify the environment. 88 | -> m a -- ^ @Reader@ to run in the modified environment. 89 | -> m a 90 | 91 | -- | Retrieves a function of the current environment. 92 | reader :: (r -> a) -- ^ The selector function to apply to the environment. 93 | -> m a 94 | reader f = do 95 | r <- ask 96 | return (f r) 97 | 98 | -- | Retrieves a function of the current environment. 99 | asks :: MonadReader r m 100 | => (r -> a) -- ^ The selector function to apply to the environment. 101 | -> m a 102 | asks = reader 103 | 104 | -- ---------------------------------------------------------------------------- 105 | -- The partially applied function type is a simple reader monad 106 | 107 | instance MonadReader r ((->) r) where 108 | ask = id 109 | local f m = m . f 110 | reader = id 111 | 112 | instance Monad m => MonadReader r (ReaderT r m) where 113 | ask = ReaderT.ask 114 | local = ReaderT.local 115 | reader = ReaderT.reader 116 | 117 | -- | @since 2.3 118 | instance (Monad m, Monoid w) => MonadReader r (CPSRWS.RWST r w s m) where 119 | ask = CPSRWS.ask 120 | local = CPSRWS.local 121 | reader = CPSRWS.reader 122 | 123 | instance (Monad m, Monoid w) => MonadReader r (LazyRWS.RWST r w s m) where 124 | ask = LazyRWS.ask 125 | local = LazyRWS.local 126 | reader = LazyRWS.reader 127 | 128 | instance (Monad m, Monoid w) => MonadReader r (StrictRWS.RWST r w s m) where 129 | ask = StrictRWS.ask 130 | local = StrictRWS.local 131 | reader = StrictRWS.reader 132 | 133 | -- --------------------------------------------------------------------------- 134 | -- Instances for other mtl transformers 135 | -- 136 | -- All of these instances need UndecidableInstances, 137 | -- because they do not satisfy the coverage condition. 138 | 139 | instance MonadReader r' m => MonadReader r' (ContT r m) where 140 | ask = lift ask 141 | local = Cont.liftLocal ask local 142 | reader = lift . reader 143 | 144 | {- | @since 2.2 -} 145 | instance MonadReader r m => MonadReader r (ExceptT e m) where 146 | ask = lift ask 147 | local = mapExceptT . local 148 | reader = lift . reader 149 | 150 | instance MonadReader r m => MonadReader r (IdentityT m) where 151 | ask = lift ask 152 | local = mapIdentityT . local 153 | reader = lift . reader 154 | 155 | instance MonadReader r m => MonadReader r (MaybeT m) where 156 | ask = lift ask 157 | local = mapMaybeT . local 158 | reader = lift . reader 159 | 160 | instance MonadReader r m => MonadReader r (Lazy.StateT s m) where 161 | ask = lift ask 162 | local = Lazy.mapStateT . local 163 | reader = lift . reader 164 | 165 | instance MonadReader r m => MonadReader r (Strict.StateT s m) where 166 | ask = lift ask 167 | local = Strict.mapStateT . local 168 | reader = lift . reader 169 | 170 | -- | @since 2.3 171 | instance (Monoid w, MonadReader r m) => MonadReader r (CPS.WriterT w m) where 172 | ask = lift ask 173 | local = CPS.mapWriterT . local 174 | reader = lift . reader 175 | 176 | instance (Monoid w, MonadReader r m) => MonadReader r (Lazy.WriterT w m) where 177 | ask = lift ask 178 | local = Lazy.mapWriterT . local 179 | reader = lift . reader 180 | 181 | instance (Monoid w, MonadReader r m) => MonadReader r (Strict.WriterT w m) where 182 | ask = lift ask 183 | local = Strict.mapWriterT . local 184 | reader = lift . reader 185 | 186 | -- | @since 2.3 187 | instance 188 | ( Monoid w 189 | , MonadReader r m 190 | ) => MonadReader r (AccumT w m) where 191 | ask = lift ask 192 | local = Accum.mapAccumT . local 193 | reader = lift . reader 194 | 195 | -- | @since 2.3 196 | instance 197 | ( MonadReader r' m 198 | ) => MonadReader r' (SelectT r m) where 199 | ask = lift ask 200 | -- there is no Select.liftLocal 201 | local f m = SelectT $ \c -> do 202 | r <- ask 203 | local f (runSelectT m (local (const r) . c)) 204 | reader = lift . reader 205 | -------------------------------------------------------------------------------- /Control/Monad/Select.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DerivingVia #-} 2 | {-# LANGUAGE FlexibleInstances #-} 3 | {-# LANGUAGE FunctionalDependencies #-} 4 | {-# LANGUAGE KindSignatures #-} 5 | {-# LANGUAGE StandaloneDeriving #-} 6 | {-# LANGUAGE Trustworthy #-} 7 | {-# LANGUAGE UndecidableInstances #-} 8 | -- Later GHCs infer DerivingVia as not Safe 9 | -- We just downgrade to Trustworthy and go fish 10 | {-# OPTIONS_GHC -Wno-trustworthy-safe #-} 11 | 12 | -- | Module: Control.Monad.Select 13 | -- Copyright: (C) Koz Ross 2022 14 | -- License: BSD-3-Clause (see the LICENSE file) 15 | -- Maintainer: koz.ross@retro-freedom.nz 16 | -- Stability: Experimental 17 | -- Portability: GHC only 18 | -- 19 | -- [Computation type:] Backtracking search, with @r@ as a \'ranking\' or 20 | -- \'evaluation\' type. 21 | -- 22 | -- [Binding strategy:] Binding a function to a monadic value \'chains together\' 23 | -- strategies; having seen the result of one search, decide which policy to use 24 | -- to continue. 25 | -- 26 | -- [Useful for:] Search problems. 27 | -- 28 | -- [Zero and plus:] None. 29 | -- 30 | -- [Example type:] @'Control.Monad.Trans.Select.Select' r a@ 31 | -- 32 | -- = A note on commutativity 33 | -- 34 | -- Some effects are /commutative/: it doesn't matter which you resolve first, as 35 | -- all possible orderings of commutative effects are isomorphic. Consider, for 36 | -- example, the reader and state effects, as exemplified by 'ReaderT' and 37 | -- 'StrictState.StateT' respectively. If we have 38 | -- @'ReaderT' r ('StrictState.State' s) a@, this is 39 | -- effectively @r -> 'StrictState.State' s a ~ r -> s -> (a, s)@; if we instead have 40 | -- @'StrictState.StateT' s ('Control.Monad.Trans.Reader.Reader' r) a@, this is effectively 41 | -- @s -> 'Control.Monad.Trans.Reader' r (a, s) ~ s -> r -> (a, s)@. Since we 42 | -- can always reorder function arguments (for example, using 'flip', as in 43 | -- this case) without changing the result, these are 44 | -- isomorphic, showing that reader and state are /commutative/, or, more 45 | -- precisely, /commute with each other/. 46 | -- 47 | -- However, this isn't generally the case. Consider instead the error and state 48 | -- effects, as exemplified by 'MaybeT' and 'StrictState.StateT' respectively. 49 | -- If we have @'MaybeT' ('Control.Monad.Trans.State.Strict.State' s) a@, this 50 | -- is effectively @'State' s ('Maybe' a) ~ s -> ('Maybe' a, s)@: put simply, 51 | -- the error can occur only in the /result/, but 52 | -- not the state, which always \'survives\'. On the other hand, if we have 53 | -- @'StrictState.StateT' s 'Maybe' a@, this is instead @s -> 'Maybe' (a, s)@: here, 54 | -- if we error, we lose /both/ the state and the result! Thus, error and state effects 55 | -- do /not/ commute with each other. 56 | -- 57 | -- As the MTL is capability-based, we support any ordering of non-commutative 58 | -- effects on an equal footing. Indeed, if you wish to use 59 | -- 'Control.Monad.State.Class.MonadState', for 60 | -- example, whether your final monadic stack ends up being @'MaybeT' 61 | -- ('Control.Monad.Trans.State.Strict.State' s) 62 | -- a@, @'StrictState.StateT' s 'Maybe' a@, or anything else, you will be able to write your 63 | -- desired code without having to consider such differences. However, the way we 64 | -- /implement/ these capabilities for any given transformer (or rather, any 65 | -- given transformed stack) /is/ affected by this ordering unless the effects in 66 | -- question are commutative. 67 | -- 68 | -- We note in this module which effects the accumulation effect does and doesn't 69 | -- commute with; we also note on implementations with non-commutative 70 | -- transformers what the outcome will be. Note that, depending on how the 71 | -- \'inner monad\' is structured, this may be more complex than we note: we 72 | -- describe only what impact the \'outer effect\' has, not what else might be in 73 | -- the stack. 74 | -- 75 | -- = Commutativity of selection 76 | -- 77 | -- The selection effect commutes with the identity effect ('IdentityT'), but 78 | -- nothing else. 79 | module Control.Monad.Select 80 | ( -- * Type class 81 | MonadSelect (..), 82 | 83 | -- * Lifting helper type 84 | LiftingSelect (..), 85 | ) 86 | where 87 | 88 | import Control.Monad.Trans.Accum (AccumT) 89 | import Control.Monad.Trans.Class (MonadTrans (lift)) 90 | import Control.Monad.Trans.Cont (ContT) 91 | import Control.Monad.Trans.Except (ExceptT) 92 | import Control.Monad.Trans.Identity (IdentityT) 93 | import Control.Monad.Trans.Maybe (MaybeT) 94 | import qualified Control.Monad.Trans.RWS.CPS as CPSRWS 95 | import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS 96 | import qualified Control.Monad.Trans.RWS.Strict as StrictRWS 97 | import Control.Monad.Trans.Reader (ReaderT) 98 | import Control.Monad.Trans.Select (SelectT) 99 | import qualified Control.Monad.Trans.Select as Select 100 | import qualified Control.Monad.Trans.State.Lazy as LazyState 101 | import qualified Control.Monad.Trans.State.Strict as StrictState 102 | import qualified Control.Monad.Trans.Writer.CPS as CPSWriter 103 | import qualified Control.Monad.Trans.Writer.Lazy as LazyWriter 104 | import qualified Control.Monad.Trans.Writer.Strict as StrictWriter 105 | import Data.Functor.Identity (Identity) 106 | import Data.Kind (Type) 107 | 108 | -- | The capability to search with backtracking. Essentially describes a 109 | -- \'policy function\': given the state of the search (and a \'ranking\' or 110 | -- \'evaluation\' of each possible result so far), pick the result that's 111 | -- currently best. 112 | -- 113 | -- = Laws 114 | -- 115 | -- Any instance of 'MonadSelect' must follow these laws: 116 | -- 117 | -- * @'select' ('const' x)@ @=@ @'pure' x@ 118 | -- * @'select' f '*>' 'select' g@ @=@ @'select' g@ 119 | -- 120 | -- @since 2.3 121 | class (Monad m) => MonadSelect r m | m -> r where 122 | select :: ((a -> r) -> a) -> m a 123 | 124 | -- | @since 2.3 125 | instance MonadSelect r (SelectT r Identity) where 126 | select = Select.select 127 | 128 | -- | \'Extends\' the possibilities considered by @m@ to include 'Nothing'; this 129 | -- means that 'Nothing' gains a \'rank\' (namely, a value of @r@), and the 130 | -- potential result could also be 'Nothing'. 131 | -- 132 | -- @since 2.3 133 | deriving via 134 | (LiftingSelect MaybeT m) 135 | instance 136 | (MonadSelect r m) => 137 | MonadSelect r (MaybeT m) 138 | 139 | -- | The continuation describes a way of choosing a \'search\' or \'ranking\' 140 | -- strategy for @r@, based on a \'ranking\' using @r'@, given any @a@. We then 141 | -- get a \'search\' strategy for @r@. 142 | -- 143 | -- @since 2.3 144 | deriving via 145 | (LiftingSelect (ContT r) m) 146 | instance 147 | (MonadSelect r' m) => 148 | MonadSelect r' (ContT r m) 149 | 150 | -- | \'Extends\' the possibilities considered by @m@ to include every value of 151 | -- @e@; this means that the potential result could be either a 'Left' (making it 152 | -- a choice of type @e@) or a 'Right' (making it a choice of type @a@). 153 | -- 154 | -- @since 2.3 155 | deriving via 156 | (LiftingSelect (ExceptT e) m) 157 | instance 158 | (MonadSelect r m) => 159 | MonadSelect r (ExceptT e m) 160 | 161 | -- | @since 2.3 162 | deriving via 163 | (LiftingSelect IdentityT m) 164 | instance 165 | (MonadSelect r m) => 166 | MonadSelect r (IdentityT m) 167 | 168 | -- | Provides a read-only environment of type @r@ to the \'strategy\' function. 169 | -- However, the \'ranking\' function (or more accurately, representation) has no 170 | -- access to @r@. Put another way, you can influence what values get chosen by 171 | -- changing @r@, but not how solutions are ranked. 172 | -- 173 | -- @since 2.3 174 | deriving via 175 | (LiftingSelect (ReaderT r) m) 176 | instance 177 | (MonadSelect r' m) => 178 | MonadSelect r' (ReaderT r m) 179 | 180 | -- | \'Readerizes\' the state: the \'ranking\' function can /see/ a value of 181 | -- type @s@, but not modify it. Effectively, can be thought of as \'extending\' 182 | -- the \'ranking\' by all values in @s@, but /which/ @s@ gets given to any rank 183 | -- calls is predetermined by the \'outer state\' (and cannot change). 184 | -- 185 | -- @since 2.3 186 | deriving via 187 | (LiftingSelect (LazyState.StateT s) m) 188 | instance 189 | (MonadSelect w m) => 190 | MonadSelect w (LazyState.StateT s m) 191 | 192 | -- | \'Readerizes\' the state: the \'ranking\' function can /see/ a value of 193 | -- type @s@, but not modify it. Effectively, can be thought of as \'extending\' 194 | -- the \'ranking\' by all values in @s@, but /which/ @s@ gets given to any rank 195 | -- calls is predetermined by the \'outer state\' (and cannot change). 196 | -- 197 | -- @since 2.3 198 | deriving via 199 | (LiftingSelect (StrictState.StateT s) m) 200 | instance 201 | (MonadSelect w m) => 202 | MonadSelect w (StrictState.StateT s m) 203 | 204 | -- | \'Readerizes\' the writer: the \'ranking\' function can see the value 205 | -- that's been accumulated (of type @w@), but can't add anything to the log. 206 | -- Effectively, can be thought of as \'extending\' the \'ranking\' by all values 207 | -- of @w@, but /which/ @w@ gets given to any rank calls is predetermined by the 208 | -- \'outer writer\' (and cannot change). 209 | -- 210 | -- @since 2.3 211 | deriving via 212 | (LiftingSelect (CPSWriter.WriterT w) m) 213 | instance 214 | (MonadSelect w' m) => 215 | MonadSelect w' (CPSWriter.WriterT w m) 216 | 217 | -- | \'Readerizes\' the writer: the \'ranking\' function can see the value 218 | -- that's been accumulated (of type @w@), but can't add anything to the log. 219 | -- Effectively, can be thought of as \'extending\' the \'ranking\' by all values 220 | -- of @w@, but /which/ @w@ gets given to any rank calls is predetermined by the 221 | -- \'outer writer\' (and cannot change). 222 | -- 223 | -- @since 2.3 224 | deriving via 225 | (LiftingSelect (LazyWriter.WriterT w) m) 226 | instance 227 | (MonadSelect w' m, Monoid w) => 228 | MonadSelect w' (LazyWriter.WriterT w m) 229 | 230 | -- | \'Readerizes\' the writer: the \'ranking\' function can see the value 231 | -- that's been accumulated (of type @w@), but can't add anything to the log. 232 | -- Effectively, can be thought of as \'extending\' the \'ranking\' by all values 233 | -- of @w@, but /which/ @w@ gets given to any rank calls is predetermined by the 234 | -- \'outer writer\' (and cannot change). 235 | -- 236 | -- @since 2.3 237 | deriving via 238 | (LiftingSelect (StrictWriter.WriterT w) m) 239 | instance 240 | (MonadSelect w' m, Monoid w) => 241 | MonadSelect w' (StrictWriter.WriterT w m) 242 | 243 | -- | A combination of an \'outer\' 'ReaderT', 'WriterT' and 'StateT'. In short, 244 | -- you get a value of type @r@ which can influence what gets picked, but not how 245 | -- anything is ranked, and the \'ranking\' function gets access to an @s@ and a 246 | -- @w@, but can modify neither. 247 | -- 248 | -- @since 2.3 249 | deriving via 250 | (LiftingSelect (CPSRWS.RWST r w s) m) 251 | instance 252 | (MonadSelect w' m) => 253 | MonadSelect w' (CPSRWS.RWST r w s m) 254 | 255 | -- | A combination of an \'outer\' 'ReaderT', 'WriterT' and 'StateT'. In short, 256 | -- you get a value of type @r@ which can influence what gets picked, but not how 257 | -- anything is ranked, and the \'ranking\' function gets access to an @s@ and a 258 | -- @w@, but can modify neither. 259 | -- 260 | -- @since 2.3 261 | deriving via 262 | (LiftingSelect (LazyRWS.RWST r w s) m) 263 | instance 264 | (MonadSelect w' m, Monoid w) => 265 | MonadSelect w' (LazyRWS.RWST r w s m) 266 | 267 | -- | A combination of an \'outer\' 'ReaderT', 'WriterT' and 'StateT'. In short, 268 | -- you get a value of type @r@ which can influence what gets picked, but not how 269 | -- anything is ranked, and the \'ranking\' function gets access to an @s@ and a 270 | -- @w@, but can modify neither. 271 | -- 272 | -- @since 2.3 273 | deriving via 274 | (LiftingSelect (StrictRWS.RWST r w s) m) 275 | instance 276 | (MonadSelect w' m, Monoid w) => 277 | MonadSelect w' (StrictRWS.RWST r w s m) 278 | 279 | -- | \'Readerizes\' the accumulator: the \'ranking\' function can see the value 280 | -- that has been accumulated (of type @w@), but can't add anything to it. 281 | -- Effectively, can be thought of as \'extending\' the \'ranking\' by all values 282 | -- of @w@, but /which/ @w@ gets given to any rank calls is predetermined by the 283 | -- \'outer accumulation\' (and cannot change). 284 | -- 285 | -- @since 2.3 286 | deriving via 287 | (LiftingSelect (AccumT w) m) 288 | instance 289 | (MonadSelect r m, Monoid w) => 290 | MonadSelect r (AccumT w m) 291 | 292 | -- | A helper type to decrease boilerplate when defining new transformer 293 | -- instances of 'MonadSelect'. 294 | -- 295 | -- Most of the instances in this module are derived using this method; for 296 | -- example, our instance of 'ExceptT' is derived as follows: 297 | -- 298 | -- > deriving via (LiftingSelect (ExceptT e) m) instance (MonadSelect r m) => 299 | -- > MonadSelect r (ExceptT e m) 300 | -- 301 | -- @since 2.3 302 | newtype LiftingSelect (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) (a :: Type) 303 | = LiftingSelect (t m a) 304 | deriving 305 | ( -- | @since 2.3 306 | Functor, 307 | -- | @since 2.3 308 | Applicative, 309 | -- | @since 2.3 310 | Monad 311 | ) 312 | via (t m) 313 | 314 | -- | @since 2.3 315 | instance (MonadTrans t, MonadSelect r m, Monad (t m)) => MonadSelect r (LiftingSelect t m) where 316 | select f = LiftingSelect . lift $ select f 317 | -------------------------------------------------------------------------------- /Control/Monad/State.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | ----------------------------------------------------------------------------- 3 | -- | 4 | -- Module : Control.Monad.State 5 | -- Copyright : (c) Andy Gill 2001, 6 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 7 | -- License : BSD-style (see the file LICENSE) 8 | -- 9 | -- Maintainer : libraries@haskell.org 10 | -- Stability : experimental 11 | -- Portability : non-portable (multi-param classes, functional dependencies) 12 | -- 13 | -- State monads. 14 | -- 15 | -- This module is inspired by the paper 16 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 17 | -- Mark P Jones () 18 | -- Advanced School of Functional Programming, 1995. 19 | 20 | ----------------------------------------------------------------------------- 21 | 22 | module Control.Monad.State ( 23 | module Control.Monad.State.Lazy 24 | ) where 25 | 26 | import Control.Monad.State.Lazy 27 | -------------------------------------------------------------------------------- /Control/Monad/State/Class.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | {-# LANGUAGE FunctionalDependencies #-} 3 | {-# LANGUAGE FlexibleInstances #-} 4 | {-# LANGUAGE MultiParamTypeClasses #-} 5 | -- Search for UndecidableInstances to see why this is needed 6 | {-# LANGUAGE UndecidableInstances #-} 7 | -- Needed because the CPSed versions of Writer and State are secretly State 8 | -- wrappers, which don't force such constraints, even though they should legally 9 | -- be there. 10 | {-# OPTIONS_GHC -Wno-redundant-constraints #-} 11 | 12 | ----------------------------------------------------------------------------- 13 | -- | 14 | -- Module : Control.Monad.State.Class 15 | -- Copyright : (c) Andy Gill 2001, 16 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 17 | -- License : BSD-style (see the file LICENSE) 18 | -- 19 | -- Maintainer : libraries@haskell.org 20 | -- Stability : experimental 21 | -- Portability : non-portable (multi-param classes, functional dependencies) 22 | -- 23 | -- MonadState class. 24 | -- 25 | -- This module is inspired by the paper 26 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 27 | -- Mark P Jones () 28 | -- Advanced School of Functional Programming, 1995. 29 | 30 | ----------------------------------------------------------------------------- 31 | 32 | module Control.Monad.State.Class ( 33 | MonadState(..), 34 | modify, 35 | modify', 36 | gets 37 | ) where 38 | 39 | import Control.Monad.Trans.Cont (ContT) 40 | import Control.Monad.Trans.Except (ExceptT) 41 | import Control.Monad.Trans.Identity (IdentityT) 42 | import Control.Monad.Trans.Maybe (MaybeT) 43 | import Control.Monad.Trans.Reader (ReaderT) 44 | import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS 45 | import qualified Control.Monad.Trans.RWS.Strict as StrictRWS 46 | import qualified Control.Monad.Trans.State.Lazy as Lazy 47 | import qualified Control.Monad.Trans.State.Strict as Strict 48 | import qualified Control.Monad.Trans.Writer.Lazy as Lazy 49 | import qualified Control.Monad.Trans.Writer.Strict as Strict 50 | import Control.Monad.Trans.Accum (AccumT) 51 | import Control.Monad.Trans.Select (SelectT) 52 | import qualified Control.Monad.Trans.RWS.CPS as CPSRWS 53 | import qualified Control.Monad.Trans.Writer.CPS as CPS 54 | import Control.Monad.Trans.Class (lift) 55 | 56 | -- --------------------------------------------------------------------------- 57 | 58 | -- | Minimal definition is either both of @get@ and @put@ or just @state@ 59 | class Monad m => MonadState s m | m -> s where 60 | -- | Return the state from the internals of the monad. 61 | get :: m s 62 | get = state (\s -> (s, s)) 63 | 64 | -- | Replace the state inside the monad. 65 | put :: s -> m () 66 | put s = state (\_ -> ((), s)) 67 | 68 | -- | Embed a simple state action into the monad. 69 | state :: (s -> (a, s)) -> m a 70 | state f = do 71 | s <- get 72 | let ~(a, s') = f s 73 | put s' 74 | return a 75 | {-# MINIMAL state | get, put #-} 76 | 77 | -- | Monadic state transformer. 78 | -- 79 | -- Maps an old state to a new state inside a state monad. 80 | -- The old state is thrown away. 81 | -- 82 | -- > Main> :t modify ((+1) :: Int -> Int) 83 | -- > modify (...) :: (MonadState Int a) => a () 84 | -- 85 | -- This says that @modify (+1)@ acts over any 86 | -- Monad that is a member of the @MonadState@ class, 87 | -- with an @Int@ state. 88 | modify :: MonadState s m => (s -> s) -> m () 89 | modify f = state (\s -> ((), f s)) 90 | 91 | -- | A variant of 'modify' in which the computation is strict in the 92 | -- new state. 93 | -- 94 | -- @since 2.2 95 | modify' :: MonadState s m => (s -> s) -> m () 96 | modify' f = do 97 | s' <- get 98 | put $! f s' 99 | 100 | -- | Gets specific component of the state, using a projection function 101 | -- supplied. 102 | gets :: MonadState s m => (s -> a) -> m a 103 | gets f = do 104 | s <- get 105 | return (f s) 106 | 107 | instance Monad m => MonadState s (Lazy.StateT s m) where 108 | get = Lazy.get 109 | put = Lazy.put 110 | state = Lazy.state 111 | 112 | instance Monad m => MonadState s (Strict.StateT s m) where 113 | get = Strict.get 114 | put = Strict.put 115 | state = Strict.state 116 | 117 | -- | @since 2.3 118 | instance (Monad m, Monoid w) => MonadState s (CPSRWS.RWST r w s m) where 119 | get = CPSRWS.get 120 | put = CPSRWS.put 121 | state = CPSRWS.state 122 | 123 | instance (Monad m, Monoid w) => MonadState s (LazyRWS.RWST r w s m) where 124 | get = LazyRWS.get 125 | put = LazyRWS.put 126 | state = LazyRWS.state 127 | 128 | instance (Monad m, Monoid w) => MonadState s (StrictRWS.RWST r w s m) where 129 | get = StrictRWS.get 130 | put = StrictRWS.put 131 | state = StrictRWS.state 132 | 133 | -- --------------------------------------------------------------------------- 134 | -- Instances for other mtl transformers 135 | -- 136 | -- All of these instances need UndecidableInstances, 137 | -- because they do not satisfy the coverage condition. 138 | 139 | instance MonadState s m => MonadState s (ContT r m) where 140 | get = lift get 141 | put = lift . put 142 | state = lift . state 143 | 144 | -- | @since 2.2 145 | instance MonadState s m => MonadState s (ExceptT e m) where 146 | get = lift get 147 | put = lift . put 148 | state = lift . state 149 | 150 | instance MonadState s m => MonadState s (IdentityT m) where 151 | get = lift get 152 | put = lift . put 153 | state = lift . state 154 | 155 | instance MonadState s m => MonadState s (MaybeT m) where 156 | get = lift get 157 | put = lift . put 158 | state = lift . state 159 | 160 | instance MonadState s m => MonadState s (ReaderT r m) where 161 | get = lift get 162 | put = lift . put 163 | state = lift . state 164 | 165 | -- | @since 2.3 166 | instance (Monoid w, MonadState s m) => MonadState s (CPS.WriterT w m) where 167 | get = lift get 168 | put = lift . put 169 | state = lift . state 170 | 171 | instance (Monoid w, MonadState s m) => MonadState s (Lazy.WriterT w m) where 172 | get = lift get 173 | put = lift . put 174 | state = lift . state 175 | 176 | instance (Monoid w, MonadState s m) => MonadState s (Strict.WriterT w m) where 177 | get = lift get 178 | put = lift . put 179 | state = lift . state 180 | 181 | -- | @since 2.3 182 | instance 183 | ( Monoid w 184 | , MonadState s m 185 | ) => MonadState s (AccumT w m) where 186 | get = lift get 187 | put = lift . put 188 | state = lift . state 189 | 190 | -- | @since 2.3 191 | instance MonadState s m => MonadState s (SelectT r m) where 192 | get = lift get 193 | put = lift . put 194 | state = lift . state 195 | -------------------------------------------------------------------------------- /Control/Monad/State/Lazy.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | ----------------------------------------------------------------------------- 3 | -- | 4 | -- Module : Control.Monad.State.Lazy 5 | -- Copyright : (c) Andy Gill 2001, 6 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 7 | -- License : BSD-style (see the file LICENSE) 8 | -- 9 | -- Maintainer : libraries@haskell.org 10 | -- Stability : experimental 11 | -- Portability : non-portable (multi-param classes, functional dependencies) 12 | -- 13 | -- Lazy state monads. 14 | -- 15 | -- This module is inspired by the paper 16 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 17 | -- Mark P Jones () 18 | -- Advanced School of Functional Programming, 1995. 19 | 20 | ----------------------------------------------------------------------------- 21 | 22 | module Control.Monad.State.Lazy ( 23 | -- * MonadState class 24 | MonadState.MonadState(..), 25 | MonadState.modify, 26 | MonadState.modify', 27 | MonadState.gets, 28 | -- * The State monad 29 | State, 30 | runState, 31 | evalState, 32 | execState, 33 | mapState, 34 | withState, 35 | -- * The StateT monad transformer 36 | StateT(StateT), 37 | runStateT, 38 | evalStateT, 39 | execStateT, 40 | mapStateT, 41 | withStateT, 42 | module Control.Monad.Trans, 43 | -- * Examples 44 | -- $examples 45 | ) where 46 | 47 | import qualified Control.Monad.State.Class as MonadState 48 | import Control.Monad.Trans 49 | 50 | import Control.Monad.Trans.State.Lazy 51 | (State, runState, evalState, execState, mapState, withState, 52 | StateT(StateT), runStateT, evalStateT, execStateT, mapStateT, withStateT) 53 | 54 | -- --------------------------------------------------------------------------- 55 | -- $examples 56 | -- A function to increment a counter. Taken from the paper 57 | -- /Generalising Monads to Arrows/, John 58 | -- Hughes (), November 1998: 59 | -- 60 | -- > tick :: State Int Int 61 | -- > tick = do n <- get 62 | -- > put (n+1) 63 | -- > return n 64 | -- 65 | -- Add one to the given number using the state monad: 66 | -- 67 | -- > plusOne :: Int -> Int 68 | -- > plusOne n = execState tick n 69 | -- 70 | -- A contrived addition example. Works only with positive numbers: 71 | -- 72 | -- > plus :: Int -> Int -> Int 73 | -- > plus n x = execState (sequence $ replicate n tick) x 74 | -- 75 | -- An example from /The Craft of Functional Programming/, Simon 76 | -- Thompson (), 77 | -- Addison-Wesley 1999: \"Given an arbitrary tree, transform it to a 78 | -- tree of integers in which the original elements are replaced by 79 | -- natural numbers, starting from 0. The same element has to be 80 | -- replaced by the same number at every occurrence, and when we meet 81 | -- an as-yet-unvisited element we have to find a \'new\' number to match 82 | -- it with:\" 83 | -- 84 | -- > data Tree a = Nil | Node a (Tree a) (Tree a) deriving (Show, Eq) 85 | -- > type Table a = [a] 86 | -- 87 | -- > numberTree :: Eq a => Tree a -> State (Table a) (Tree Int) 88 | -- > numberTree Nil = return Nil 89 | -- > numberTree (Node x t1 t2) 90 | -- > = do num <- numberNode x 91 | -- > nt1 <- numberTree t1 92 | -- > nt2 <- numberTree t2 93 | -- > return (Node num nt1 nt2) 94 | -- > where 95 | -- > numberNode :: Eq a => a -> State (Table a) Int 96 | -- > numberNode x 97 | -- > = do table <- get 98 | -- > (newTable, newPos) <- return (nNode x table) 99 | -- > put newTable 100 | -- > return newPos 101 | -- > nNode:: (Eq a) => a -> Table a -> (Table a, Int) 102 | -- > nNode x table 103 | -- > = case (findIndexInList (== x) table) of 104 | -- > Nothing -> (table ++ [x], length table) 105 | -- > Just i -> (table, i) 106 | -- > findIndexInList :: (a -> Bool) -> [a] -> Maybe Int 107 | -- > findIndexInList = findIndexInListHelp 0 108 | -- > findIndexInListHelp _ _ [] = Nothing 109 | -- > findIndexInListHelp count f (h:t) 110 | -- > = if (f h) 111 | -- > then Just count 112 | -- > else findIndexInListHelp (count+1) f t 113 | -- 114 | -- numTree applies numberTree with an initial state: 115 | -- 116 | -- > numTree :: (Eq a) => Tree a -> Tree Int 117 | -- > numTree t = evalState (numberTree t) [] 118 | -- 119 | -- > testTree = Node "Zero" (Node "One" (Node "Two" Nil Nil) (Node "One" (Node "Zero" Nil Nil) Nil)) Nil 120 | -- > numTree testTree => Node 0 (Node 1 (Node 2 Nil Nil) (Node 1 (Node 0 Nil Nil) Nil)) Nil 121 | -- 122 | -- sumTree is a little helper function that does not use the State monad: 123 | -- 124 | -- > sumTree :: (Num a) => Tree a -> a 125 | -- > sumTree Nil = 0 126 | -- > sumTree (Node e t1 t2) = e + (sumTree t1) + (sumTree t2) 127 | -------------------------------------------------------------------------------- /Control/Monad/State/Strict.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | ----------------------------------------------------------------------------- 3 | -- | 4 | -- Module : Control.Monad.State.Strict 5 | -- Copyright : (c) Andy Gill 2001, 6 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 7 | -- License : BSD-style (see the file LICENSE) 8 | -- 9 | -- Maintainer : libraries@haskell.org 10 | -- Stability : experimental 11 | -- Portability : non-portable (multi-param classes, functional dependencies) 12 | -- 13 | -- Strict state monads. 14 | -- 15 | -- This module is inspired by the paper 16 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 17 | -- Mark P Jones () 18 | -- Advanced School of Functional Programming, 1995. 19 | 20 | ----------------------------------------------------------------------------- 21 | 22 | module Control.Monad.State.Strict ( 23 | -- * MonadState class 24 | MonadState.MonadState(..), 25 | MonadState.modify, 26 | MonadState.modify', 27 | MonadState.gets, 28 | -- * The State monad 29 | State, 30 | runState, 31 | evalState, 32 | execState, 33 | mapState, 34 | withState, 35 | -- * The StateT monad transformer 36 | StateT(StateT), 37 | runStateT, 38 | evalStateT, 39 | execStateT, 40 | mapStateT, 41 | withStateT, 42 | module Control.Monad.Trans, 43 | -- * Examples 44 | -- $examples 45 | ) where 46 | 47 | import qualified Control.Monad.State.Class as MonadState 48 | import Control.Monad.Trans 49 | 50 | import Control.Monad.Trans.State.Strict 51 | (State, runState, evalState, execState, mapState, withState, 52 | StateT(StateT), runStateT, evalStateT, execStateT, mapStateT, withStateT) 53 | 54 | -- --------------------------------------------------------------------------- 55 | -- $examples 56 | -- A function to increment a counter. Taken from the paper 57 | -- /Generalising Monads to Arrows/, John 58 | -- Hughes (), November 1998: 59 | -- 60 | -- > tick :: State Int Int 61 | -- > tick = do n <- get 62 | -- > put (n+1) 63 | -- > return n 64 | -- 65 | -- Add one to the given number using the state monad: 66 | -- 67 | -- > plusOne :: Int -> Int 68 | -- > plusOne n = execState tick n 69 | -- 70 | -- A contrived addition example. Works only with positive numbers: 71 | -- 72 | -- > plus :: Int -> Int -> Int 73 | -- > plus n x = execState (sequence $ replicate n tick) x 74 | -- 75 | -- An example from /The Craft of Functional Programming/, Simon 76 | -- Thompson (), 77 | -- Addison-Wesley 1999: \"Given an arbitrary tree, transform it to a 78 | -- tree of integers in which the original elements are replaced by 79 | -- natural numbers, starting from 0. The same element has to be 80 | -- replaced by the same number at every occurrence, and when we meet 81 | -- an as-yet-unvisited element we have to find a \'new\' number to match 82 | -- it with:\" 83 | -- 84 | -- > data Tree a = Nil | Node a (Tree a) (Tree a) deriving (Show, Eq) 85 | -- > type Table a = [a] 86 | -- 87 | -- > numberTree :: Eq a => Tree a -> State (Table a) (Tree Int) 88 | -- > numberTree Nil = return Nil 89 | -- > numberTree (Node x t1 t2) 90 | -- > = do num <- numberNode x 91 | -- > nt1 <- numberTree t1 92 | -- > nt2 <- numberTree t2 93 | -- > return (Node num nt1 nt2) 94 | -- > where 95 | -- > numberNode :: Eq a => a -> State (Table a) Int 96 | -- > numberNode x 97 | -- > = do table <- get 98 | -- > (newTable, newPos) <- return (nNode x table) 99 | -- > put newTable 100 | -- > return newPos 101 | -- > nNode:: (Eq a) => a -> Table a -> (Table a, Int) 102 | -- > nNode x table 103 | -- > = case (findIndexInList (== x) table) of 104 | -- > Nothing -> (table ++ [x], length table) 105 | -- > Just i -> (table, i) 106 | -- > findIndexInList :: (a -> Bool) -> [a] -> Maybe Int 107 | -- > findIndexInList = findIndexInListHelp 0 108 | -- > findIndexInListHelp _ _ [] = Nothing 109 | -- > findIndexInListHelp count f (h:t) 110 | -- > = if (f h) 111 | -- > then Just count 112 | -- > else findIndexInListHelp (count+1) f t 113 | -- 114 | -- numTree applies numberTree with an initial state: 115 | -- 116 | -- > numTree :: (Eq a) => Tree a -> Tree Int 117 | -- > numTree t = evalState (numberTree t) [] 118 | -- 119 | -- > testTree = Node "Zero" (Node "One" (Node "Two" Nil Nil) (Node "One" (Node "Zero" Nil Nil) Nil)) Nil 120 | -- > numTree testTree => Node 0 (Node 1 (Node 2 Nil Nil) (Node 1 (Node 0 Nil Nil) Nil)) Nil 121 | -- 122 | -- sumTree is a little helper function that does not use the State monad: 123 | -- 124 | -- > sumTree :: (Num a) => Tree a -> a 125 | -- > sumTree Nil = 0 126 | -- > sumTree (Node e t1 t2) = e + (sumTree t1) + (sumTree t2) 127 | -------------------------------------------------------------------------------- /Control/Monad/Trans.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | ----------------------------------------------------------------------------- 3 | -- | 4 | -- Module : Control.Monad.Trans 5 | -- Copyright : (c) Andy Gill 2001, 6 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 7 | -- License : BSD-style (see the file LICENSE) 8 | -- 9 | -- Maintainer : libraries@haskell.org 10 | -- Stability : experimental 11 | -- Portability : portable 12 | -- 13 | -- Classes for monad transformers. 14 | -- 15 | -- A monad transformer makes new monad out of an existing monad, such 16 | -- that computations of the old monad may be embedded in the new one. 17 | -- To construct a monad with a desired set of features, one typically 18 | -- starts with a base monad, such as @Identity@, @[]@ or 'IO', and 19 | -- applies a sequence of monad transformers. 20 | -- 21 | -- Most monad transformer modules include the special case of applying the 22 | -- transformer to @Identity@. For example, @State s@ is an abbreviation 23 | -- for @StateT s Identity@. 24 | -- 25 | -- Each monad transformer also comes with an operation @run@/XXX/ to 26 | -- unwrap the transformer, exposing a computation of the inner monad. 27 | ----------------------------------------------------------------------------- 28 | 29 | module Control.Monad.Trans ( 30 | module Control.Monad.Trans.Class, 31 | module Control.Monad.IO.Class 32 | ) where 33 | 34 | import Control.Monad.IO.Class 35 | import Control.Monad.Trans.Class 36 | -------------------------------------------------------------------------------- /Control/Monad/Writer.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | ----------------------------------------------------------------------------- 4 | -- | 5 | -- Module : Control.Monad.Writer 6 | -- Copyright : (c) Andy Gill 2001, 7 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 8 | -- License : BSD-style (see the file LICENSE) 9 | -- 10 | -- Maintainer : libraries@haskell.org 11 | -- Stability : experimental 12 | -- Portability : non-portable (multi-param classes, functional dependencies) 13 | -- 14 | -- The MonadWriter class. 15 | -- 16 | -- Inspired by the paper 17 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 18 | -- Mark P Jones () 19 | -- Advanced School of Functional Programming, 1995. 20 | ----------------------------------------------------------------------------- 21 | 22 | module Control.Monad.Writer ( 23 | module Control.Monad.Writer.Lazy 24 | ) where 25 | 26 | import Control.Monad.Writer.Lazy 27 | -------------------------------------------------------------------------------- /Control/Monad/Writer/CPS.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | ----------------------------------------------------------------------------- 3 | -- | 4 | -- Module : Control.Monad.Writer.Strict 5 | -- Copyright : (c) Andy Gill 2001, 6 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 7 | -- License : BSD-style (see the file LICENSE) 8 | -- 9 | -- Maintainer : libraries@haskell.org 10 | -- Stability : experimental 11 | -- Portability : non-portable (multi-param classes, functional dependencies) 12 | -- 13 | -- Strict writer monads that use continuation-passing-style to achieve constant 14 | -- space usage. 15 | -- 16 | -- Inspired by the paper 17 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 18 | -- Mark P Jones () 19 | -- Advanced School of Functional Programming, 1995. 20 | -- 21 | -- /Since: mtl-2.3, transformers-0.5.6/ 22 | ----------------------------------------------------------------------------- 23 | 24 | module Control.Monad.Writer.CPS ( 25 | -- * MonadWriter class 26 | MonadWriter.MonadWriter(..), 27 | MonadWriter.listens, 28 | MonadWriter.censor, 29 | -- * The Writer monad 30 | Writer, 31 | runWriter, 32 | execWriter, 33 | mapWriter, 34 | -- * The WriterT monad transformer 35 | WriterT, 36 | writerT, 37 | runWriterT, 38 | execWriterT, 39 | mapWriterT, 40 | module Control.Monad.Trans, 41 | ) where 42 | 43 | import qualified Control.Monad.Writer.Class as MonadWriter 44 | import Control.Monad.Trans 45 | import Control.Monad.Trans.Writer.CPS ( 46 | Writer, runWriter, execWriter, mapWriter, 47 | WriterT, writerT, runWriterT, execWriterT, mapWriterT) 48 | -------------------------------------------------------------------------------- /Control/Monad/Writer/Class.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | {-# LANGUAGE FlexibleInstances #-} 3 | {-# LANGUAGE FunctionalDependencies #-} 4 | {-# LANGUAGE MultiParamTypeClasses #-} 5 | {-# LANGUAGE UndecidableInstances #-} 6 | -- Search for UndecidableInstances to see why this is needed 7 | 8 | ----------------------------------------------------------------------------- 9 | -- | 10 | -- Module : Control.Monad.Writer.Class 11 | -- Copyright : (c) Andy Gill 2001, 12 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 13 | -- License : BSD-style (see the file LICENSE) 14 | -- 15 | -- Maintainer : libraries@haskell.org 16 | -- Stability : experimental 17 | -- Portability : non-portable (multi-param classes, functional dependencies) 18 | -- 19 | -- The MonadWriter class. 20 | -- 21 | -- Inspired by the paper 22 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 23 | -- Mark P Jones () 24 | -- Advanced School of Functional Programming, 1995. 25 | ----------------------------------------------------------------------------- 26 | 27 | module Control.Monad.Writer.Class ( 28 | MonadWriter(..), 29 | listens, 30 | censor, 31 | ) where 32 | 33 | import Control.Monad.Trans.Except (ExceptT) 34 | import qualified Control.Monad.Trans.Except as Except 35 | import Control.Monad.Trans.Identity (IdentityT) 36 | import qualified Control.Monad.Trans.Identity as Identity 37 | import Control.Monad.Trans.Maybe (MaybeT) 38 | import qualified Control.Monad.Trans.Maybe as Maybe 39 | import Control.Monad.Trans.Reader (ReaderT, mapReaderT) 40 | import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS 41 | import qualified Control.Monad.Trans.RWS.Strict as StrictRWS 42 | import qualified Control.Monad.Trans.State.Lazy as Lazy 43 | import qualified Control.Monad.Trans.State.Strict as Strict 44 | import qualified Control.Monad.Trans.Writer.Lazy as Lazy 45 | import qualified Control.Monad.Trans.Writer.Strict as Strict 46 | import Control.Monad.Trans.Accum (AccumT) 47 | import qualified Control.Monad.Trans.Accum as Accum 48 | import qualified Control.Monad.Trans.RWS.CPS as CPSRWS 49 | import qualified Control.Monad.Trans.Writer.CPS as CPS 50 | import Control.Monad.Trans.Class (lift) 51 | 52 | -- --------------------------------------------------------------------------- 53 | -- MonadWriter class 54 | -- 55 | -- tell is like tell on the MUD's it shouts to monad 56 | -- what you want to be heard. The monad carries this 'packet' 57 | -- upwards, merging it if needed (hence the Monoid requirement). 58 | -- 59 | -- listen listens to a monad acting, and returns what the monad "said". 60 | -- 61 | -- pass lets you provide a writer transformer which changes internals of 62 | -- the written object. 63 | 64 | class (Monoid w, Monad m) => MonadWriter w m | m -> w where 65 | {-# MINIMAL (writer | tell), listen, pass #-} 66 | -- | @'writer' (a,w)@ embeds a simple writer action. 67 | writer :: (a,w) -> m a 68 | writer ~(a, w) = do 69 | tell w 70 | return a 71 | 72 | -- | @'tell' w@ is an action that produces the output @w@. 73 | tell :: w -> m () 74 | tell w = writer ((),w) 75 | 76 | -- | @'listen' m@ is an action that executes the action @m@ and adds 77 | -- its output to the value of the computation. 78 | listen :: m a -> m (a, w) 79 | -- | @'pass' m@ is an action that executes the action @m@, which 80 | -- returns a value and a function, and returns the value, applying 81 | -- the function to the output. 82 | pass :: m (a, w -> w) -> m a 83 | 84 | -- | @'listens' f m@ is an action that executes the action @m@ and adds 85 | -- the result of applying @f@ to the output to the value of the computation. 86 | -- 87 | -- * @'listens' f m = 'liftM' (id *** f) ('listen' m)@ 88 | listens :: MonadWriter w m => (w -> b) -> m a -> m (a, b) 89 | listens f m = do 90 | ~(a, w) <- listen m 91 | return (a, f w) 92 | 93 | -- | @'censor' f m@ is an action that executes the action @m@ and 94 | -- applies the function @f@ to its output, leaving the return value 95 | -- unchanged. 96 | -- 97 | -- * @'censor' f m = 'pass' ('liftM' (\\x -> (x,f)) m)@ 98 | censor :: MonadWriter w m => (w -> w) -> m a -> m a 99 | censor f m = pass $ do 100 | a <- m 101 | return (a, f) 102 | 103 | -- | @since 2.2.2 104 | instance (Monoid w) => MonadWriter w ((,) w) where 105 | writer ~(a, w) = (w, a) 106 | tell w = (w, ()) 107 | listen ~(w, a) = (w, (a, w)) 108 | pass ~(w, (a, f)) = (f w, a) 109 | 110 | -- | @since 2.3 111 | instance (Monoid w, Monad m) => MonadWriter w (CPS.WriterT w m) where 112 | writer = CPS.writer 113 | tell = CPS.tell 114 | listen = CPS.listen 115 | pass = CPS.pass 116 | 117 | instance (Monoid w, Monad m) => MonadWriter w (Lazy.WriterT w m) where 118 | writer = Lazy.writer 119 | tell = Lazy.tell 120 | listen = Lazy.listen 121 | pass = Lazy.pass 122 | 123 | instance (Monoid w, Monad m) => MonadWriter w (Strict.WriterT w m) where 124 | writer = Strict.writer 125 | tell = Strict.tell 126 | listen = Strict.listen 127 | pass = Strict.pass 128 | 129 | -- | @since 2.3 130 | instance (Monoid w, Monad m) => MonadWriter w (CPSRWS.RWST r w s m) where 131 | writer = CPSRWS.writer 132 | tell = CPSRWS.tell 133 | listen = CPSRWS.listen 134 | pass = CPSRWS.pass 135 | 136 | instance (Monoid w, Monad m) => MonadWriter w (LazyRWS.RWST r w s m) where 137 | writer = LazyRWS.writer 138 | tell = LazyRWS.tell 139 | listen = LazyRWS.listen 140 | pass = LazyRWS.pass 141 | 142 | instance (Monoid w, Monad m) => MonadWriter w (StrictRWS.RWST r w s m) where 143 | writer = StrictRWS.writer 144 | tell = StrictRWS.tell 145 | listen = StrictRWS.listen 146 | pass = StrictRWS.pass 147 | 148 | -- --------------------------------------------------------------------------- 149 | -- Instances for other mtl transformers 150 | -- 151 | -- All of these instances need UndecidableInstances, 152 | -- because they do not satisfy the coverage condition. 153 | 154 | -- | @since 2.2 155 | instance MonadWriter w m => MonadWriter w (ExceptT e m) where 156 | writer = lift . writer 157 | tell = lift . tell 158 | listen = Except.liftListen listen 159 | pass = Except.liftPass pass 160 | 161 | instance MonadWriter w m => MonadWriter w (IdentityT m) where 162 | writer = lift . writer 163 | tell = lift . tell 164 | listen = Identity.mapIdentityT listen 165 | pass = Identity.mapIdentityT pass 166 | 167 | instance MonadWriter w m => MonadWriter w (MaybeT m) where 168 | writer = lift . writer 169 | tell = lift . tell 170 | listen = Maybe.liftListen listen 171 | pass = Maybe.liftPass pass 172 | 173 | instance MonadWriter w m => MonadWriter w (ReaderT r m) where 174 | writer = lift . writer 175 | tell = lift . tell 176 | listen = mapReaderT listen 177 | pass = mapReaderT pass 178 | 179 | instance MonadWriter w m => MonadWriter w (Lazy.StateT s m) where 180 | writer = lift . writer 181 | tell = lift . tell 182 | listen = Lazy.liftListen listen 183 | pass = Lazy.liftPass pass 184 | 185 | instance MonadWriter w m => MonadWriter w (Strict.StateT s m) where 186 | writer = lift . writer 187 | tell = lift . tell 188 | listen = Strict.liftListen listen 189 | pass = Strict.liftPass pass 190 | 191 | -- | There are two valid instances for 'AccumT'. It could either: 192 | -- 193 | -- 1. Lift the operations to the inner @MonadWriter@ 194 | -- 2. Handle the operations itself, à la a @WriterT@. 195 | -- 196 | -- This instance chooses (1), reflecting that the intent 197 | -- of 'AccumT' as a type is different than that of @WriterT@. 198 | -- 199 | -- @since 2.3 200 | instance 201 | ( Monoid w' 202 | , MonadWriter w m 203 | ) => MonadWriter w (AccumT w' m) where 204 | writer = lift . writer 205 | tell = lift . tell 206 | listen = Accum.liftListen listen 207 | pass = Accum.liftPass pass 208 | -------------------------------------------------------------------------------- /Control/Monad/Writer/Lazy.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | ----------------------------------------------------------------------------- 3 | -- | 4 | -- Module : Control.Monad.Writer.Lazy 5 | -- Copyright : (c) Andy Gill 2001, 6 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 7 | -- License : BSD-style (see the file LICENSE) 8 | -- 9 | -- Maintainer : libraries@haskell.org 10 | -- Stability : experimental 11 | -- Portability : non-portable (multi-param classes, functional dependencies) 12 | -- 13 | -- Lazy writer monads. 14 | -- 15 | -- Inspired by the paper 16 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 17 | -- Mark P Jones () 18 | -- Advanced School of Functional Programming, 1995. 19 | ----------------------------------------------------------------------------- 20 | 21 | module Control.Monad.Writer.Lazy ( 22 | -- * MonadWriter class 23 | MonadWriter.MonadWriter(..), 24 | MonadWriter.listens, 25 | MonadWriter.censor, 26 | -- * The Writer monad 27 | Writer, 28 | runWriter, 29 | execWriter, 30 | mapWriter, 31 | -- * The WriterT monad transformer 32 | WriterT(WriterT), 33 | runWriterT, 34 | execWriterT, 35 | mapWriterT, 36 | module Control.Monad.Trans, 37 | ) where 38 | 39 | import qualified Control.Monad.Writer.Class as MonadWriter 40 | import Control.Monad.Trans 41 | import Control.Monad.Trans.Writer.Lazy ( 42 | Writer, runWriter, execWriter, mapWriter, 43 | WriterT(WriterT), runWriterT, execWriterT, mapWriterT) 44 | -------------------------------------------------------------------------------- /Control/Monad/Writer/Strict.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | ----------------------------------------------------------------------------- 3 | -- | 4 | -- Module : Control.Monad.Writer.Strict 5 | -- Copyright : (c) Andy Gill 2001, 6 | -- (c) Oregon Graduate Institute of Science and Technology, 2001 7 | -- License : BSD-style (see the file LICENSE) 8 | -- 9 | -- Maintainer : libraries@haskell.org 10 | -- Stability : experimental 11 | -- Portability : non-portable (multi-param classes, functional dependencies) 12 | -- 13 | -- Strict writer monads. 14 | -- 15 | -- Inspired by the paper 16 | -- /Functional Programming with Overloading and Higher-Order Polymorphism/, 17 | -- Mark P Jones () 18 | -- Advanced School of Functional Programming, 1995. 19 | ----------------------------------------------------------------------------- 20 | 21 | module Control.Monad.Writer.Strict ( 22 | -- * MonadWriter class 23 | MonadWriter.MonadWriter(..), 24 | MonadWriter.listens, 25 | MonadWriter.censor, 26 | -- * The Writer monad 27 | Writer, 28 | runWriter, 29 | execWriter, 30 | mapWriter, 31 | -- * The WriterT monad transformer 32 | WriterT(..), 33 | execWriterT, 34 | mapWriterT, 35 | module Control.Monad.Trans, 36 | ) where 37 | 38 | import qualified Control.Monad.Writer.Class as MonadWriter 39 | import Control.Monad.Trans 40 | import Control.Monad.Trans.Writer.Strict ( 41 | Writer, runWriter, execWriter, mapWriter, 42 | WriterT(..), execWriterT, mapWriterT) 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The Glasgow Haskell Compiler License 2 | 3 | Copyright 2004, The University Court of the University of Glasgow. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | - Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | - Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | - Neither name of the University nor the names of its contributors may be 17 | used to endorse or promote products derived from this software without 18 | specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF 21 | GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 22 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 23 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE 25 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | DAMAGE. 32 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # `mtl` [![Hackage](https://img.shields.io/hackage/v/mtl.svg)](https://hackage.haskell.org/package/mtl) [![Build Status](https://travis-ci.org/haskell/mtl.svg)](https://travis-ci.org/haskell/mtl) 2 | 3 | MTL is a collection of monad classes, extending the `transformers` 4 | package, using functional dependencies for generic lifting of monadic 5 | actions. 6 | 7 | ## Structure 8 | 9 | Transformers in MTL are divided into classes and data types. Classes 10 | define the monadic operations of transformers. Data types, generally 11 | from the `transformers` package, implement transformers, and MTL 12 | provides instances for all the transformer type classes. 13 | 14 | MTL and `transformers` use a common module, data type, and function 15 | naming scheme. As an example, let's imagine we have a transformer 16 | `Foo`. 17 | 18 | In the `Control.Monad.Foo` module, we'd find: 19 | 20 | * A type class `MonadFoo` with the transformer operations. 21 | * A data type `FooT` with instances for all monad transformer classes. 22 | * Functions to run the transformed computation, e.g. `runFooT`. For 23 | the actual transformers, there are usually a number of useful runner 24 | functions. 25 | 26 | ### Lifting 27 | 28 | When using monad transformers, you often need to "lift" a monadic 29 | action into your transformed monadic action. This is done using the 30 | `lift` function from `MonadTrans` in the `Control.Monad.Trans.Class` 31 | module: 32 | 33 | ``` haskell 34 | lift :: (Monad m, MonadTrans t) => m a -> t m a 35 | ``` 36 | 37 | The action `m a` is lifted into the transformer action `t m a`. 38 | 39 | As an example, here we lift an action of type `IO a` into an action of 40 | type `ExceptT MyError IO a`: 41 | 42 | ``` haskell 43 | data MyError = EmptyLine 44 | 45 | mightFail :: ExceptT MyError IO () 46 | mightFail = do 47 | l <- lift getLine 48 | when (null l) (throwError EmptyLine) 49 | ``` 50 | 51 | ### Transformers 52 | 53 | The following outlines the available monad classes and transformers in 54 | MTL and `transformers`. For more details, and the corresponding 55 | documentation of the `mtl` version you are using, see [the 56 | documentation on Hackage](https://hackage.haskell.org/package/mtl). 57 | 58 | * `Control.Monad.Cont` 59 | 60 | The Continuation monad transformer adds the ability to use 61 | [continuation-passing style 62 | (CPS)](https://en.wikipedia.org/wiki/Continuation-passing_style) 63 | in a monadic computation. Continuations can be used to manipulate 64 | the control flow of a program, e.g. early exit, error handling, or 65 | suspending a computation. 66 | 67 | - Class: `Control.Monad.Cont.Class.MonadCont` 68 | - Transformer: `Control.Monad.Cont.ContT` 69 | 70 | * `Control.Monad.Error` (deprecated!) 71 | 72 | The Error monad transformer has been deprecated in favor of 73 | `Control.Monad.Except`. 74 | 75 | * `Control.Monad.Except` 76 | 77 | The Except monad transformer adds the ability to fail with an 78 | error in a monadic computation. 79 | 80 | - Class: `Control.Monad.Except.Class.MonadError` 81 | - Transformer: `Control.Monad.Except.ExceptT` 82 | 83 | * `Control.Monad.Identity` 84 | 85 | The Identity monad transformer does not add any abilities to a 86 | monad. It simply applies the bound function to its inner monad 87 | without any modification. 88 | 89 | - Transformer: `Control.Monad.Trans.Identity.IdentityT` (in the `transformers` package) 90 | - Identity functor and monad: `Data.Functor.Identity.Identity` (in the `base` package) 91 | 92 | * `Control.Monad.RWS` 93 | 94 | A convenient transformer that combines the Reader, Writer, and 95 | State monad transformers. 96 | 97 | - Lazy transformer: `Control.Monad.RWS.Lazy.RWST` (which is the default, exported by `Control.Monad.RWS`) 98 | - Strict transformer: `Control.Monad.RWS.Strict.RWST` 99 | 100 | * `Control.Monad.Reader` 101 | 102 | The Reader monad transformer represents a computation which can 103 | read values from an environment. 104 | 105 | - Class: `Control.Monad.Reader.Class.MonadReader` 106 | - Transformer: `Control.Monad.Reader.ReaderT` 107 | 108 | * `Control.Monad.State` 109 | 110 | The State monad transformer represents a computation which can 111 | read and write internal state values. If you only need to _read_ 112 | values, you might want to use 113 | [Reader](http://hackage.haskell.org/package/mtl/docs/Control-Monad-Reader.html) 114 | instead. 115 | 116 | - Class: `Control.Monad.State.Class.MonadState` 117 | - Lazy transformer: `Control.Monad.State.Lazy.StateT` (the default, exported by `Control.Monad.State`) 118 | - Strict transformer: `Control.Monad.State.Strict.StateT` 119 | 120 | * `Control.Monad.Writer` 121 | 122 | The Writer monad transformer represents a computation that can 123 | produce a stream of data in addition to the computed values. This 124 | can be used to collect values in some data structure with a 125 | `Monoid` instance. This can be used for things like logging and 126 | accumulating values throughout a computation. 127 | 128 | - Class: `Control.Monad.Writer.Class.MonadWriter` 129 | - Lazy transformers: `Control.Monad.Writer.Lazy.WriterT` 130 | - Strict transformers: `Control.Monad.Writer.Strict.WriterT` 131 | 132 | * `Control.Monad.Accum` 133 | 134 | The `Accum` monad transformer represents a computation which 135 | manages append-only state, or a writer that can read all 136 | previous inputs. It binds a function to a monadic value by 137 | lazily accumulating subcomputations via `(<>)`. For more general 138 | access, use [State](https://hackage.haskell.org/package/transformers-0.6.0.4/docs/Control-Monad-Trans-State.html) instead. 139 | 140 | - Class: `Control.Monad.Accum` 141 | - Transformer: `Control.Monad.Trans.Accum.AccumT` 142 | 143 | * `Control.Monad.Select` 144 | 145 | The `Select` monad transformer represents a computation which 146 | can do backtracking search using a 'ranked' evaluation strategy. 147 | Binding a function to a monad value chains together evaluation 148 | strategies in the sense that the results of previous strategies 149 | may influence subsequent rank and evaluation strategies in 150 | subcomputations. 151 | 152 | - Class: `Control.Monad.Select` 153 | - Transformer: `Control.Monad.Trans.Select.SelectT` 154 | 155 | ## Resources 156 | 157 | * [`mtl` on Hackage](http://hackage.haskell.org/package/mtl) 158 | * The [Monad Transformers](http://dev.stephendiehl.com/hask/#monad-transformers) 159 | chapter in "What I Wish I Knew When Learning Haskell". 160 | * References: 161 | - This package is inspired by the paper _Functional Programming 162 | with Overloading and Higher-Order Polymorphism_, by Mark P 163 | Jones, in _Advanced School of Functional Programming_, 1995 164 | (). 165 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /cabal.project: -------------------------------------------------------------------------------- 1 | packages: ./mtl.cabal 2 | 3 | package mtl 4 | ghc-options: -Werror 5 | -------------------------------------------------------------------------------- /docs/Mtl-2.3.x-Migration.md: -------------------------------------------------------------------------------- 1 | # Migrating to `mtl-2.3.x` 2 | 3 | In `mtl-2.3.x`, [re-exports were removed](https://github.com/haskell/mtl/pull/108) from the library in order to achieve PVP compliance, as well as disentangle some historical warts in its design. This was a breaking change that maintainers decided was in the `mtl`'s best interest due to the re-exports overlapping with `base`, as well as generally being confusing and outdated for modern GHC versions. While all changes were detailed in the changelog, navigating the removal of re-exports can be tricky. Below is a detailed review of what needs to be done to use the new `mtl`. 4 | 5 | ## Removed re-exports 6 | 7 | The following `base`-specific re-exports were cut from many modules: 8 | 9 | - `Control.Monad` 10 | - `Control.Monad.Fix` 11 | - `Data.Monoid` 12 | 13 | In `mtl-2.3`, the following export was erroneously removed from `mtl`-specific modules: 14 | 15 | - `ExceptT` and related functions from `Control.Monad.Except` 16 | 17 | ## What do I need to do? 18 | 19 | First, update your `*.cabal` file to point to the new `mtl-2.3.1` release (currently on Hackage), or add the following to your `cabal.project`: 20 | 21 | 22 | ``` 23 | packages: . 24 | 25 | source-repository-package 26 | type: git 27 | location: https://github.com/haskell/mtl 28 | tag: v2.3.1 29 | 30 | allow-newer: 31 | *:mtl 32 | ``` 33 | 34 | Now, if upon recompile you see anything to the effect that particular functions from any of the above re-exports are missing, then you'll need to import the modules explicitly in order to expose the functions. 35 | -------------------------------------------------------------------------------- /mtl.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: 3.0 2 | name: mtl 3 | version: 2.3.1 4 | license: BSD-3-Clause 5 | license-file: LICENSE 6 | author: Andy Gill 7 | maintainer: chessai , 8 | Emily Pillmore , 9 | Koz Ross 10 | category: Control 11 | synopsis: Monad classes for transformers, using functional dependencies 12 | homepage: http://github.com/haskell/mtl 13 | bug-reports: http://github.com/haskell/mtl/issues 14 | description: 15 | MTL is a collection of monad classes, extending the 'transformers' 16 | package, using functional dependencies for generic lifting of 17 | monadic actions. 18 | 19 | build-type: Simple 20 | 21 | extra-source-files: 22 | CHANGELOG.markdown 23 | README.markdown 24 | 25 | tested-with: GHC ==8.6.5 || ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.4 || ==9.4.1 26 | 27 | source-repository head 28 | type: git 29 | location: https://github.com/haskell/mtl.git 30 | 31 | Library 32 | exposed-modules: 33 | Control.Monad.Cont 34 | Control.Monad.Cont.Class 35 | Control.Monad.Error.Class 36 | Control.Monad.Except 37 | Control.Monad.Identity 38 | Control.Monad.RWS 39 | Control.Monad.RWS.Class 40 | Control.Monad.RWS.CPS 41 | Control.Monad.RWS.Lazy 42 | Control.Monad.RWS.Strict 43 | Control.Monad.Reader 44 | Control.Monad.Reader.Class 45 | Control.Monad.State 46 | Control.Monad.State.Class 47 | Control.Monad.State.Lazy 48 | Control.Monad.State.Strict 49 | Control.Monad.Trans 50 | Control.Monad.Writer 51 | Control.Monad.Writer.Class 52 | Control.Monad.Writer.CPS 53 | Control.Monad.Writer.Lazy 54 | Control.Monad.Writer.Strict 55 | Control.Monad.Accum 56 | Control.Monad.Select 57 | 58 | build-depends: 59 | , base >=4.12 && < 5 60 | , transformers >= 0.5.6 && <0.7 61 | 62 | ghc-options: 63 | -Wall -Wcompat -Wincomplete-record-updates 64 | -Wincomplete-uni-patterns -Wredundant-constraints 65 | -Wmissing-export-lists 66 | 67 | default-language: Haskell2010 68 | --------------------------------------------------------------------------------