packages feed

exceptions 0.10.5 → 0.10.6

raw patch · 13 files changed

+1729/−1709 lines, 13 filesdep +call-stackdep ~basedep ~template-haskellsetup-changedPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: call-stack

Dependency ranges changed: base, template-haskell

API changes (from Hackage documentation)

- Control.Monad.Catch: bracket :: MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b
+ Control.Monad.Catch: bracket :: (HasCallStack, MonadMask m) => m a -> (a -> m c) -> (a -> m b) -> m b
- Control.Monad.Catch: bracketOnError :: MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b
+ Control.Monad.Catch: bracketOnError :: (HasCallStack, MonadMask m) => m a -> (a -> m c) -> (a -> m b) -> m b
- Control.Monad.Catch: bracket_ :: MonadMask m => m a -> m c -> m b -> m b
+ Control.Monad.Catch: bracket_ :: (HasCallStack, MonadMask m) => m a -> m c -> m b -> m b
- Control.Monad.Catch: catch :: (MonadCatch m, Exception e) => m a -> (e -> m a) -> m a
+ Control.Monad.Catch: catch :: (MonadCatch m, HasCallStack, Exception e) => m a -> (e -> m a) -> m a
- Control.Monad.Catch: catchAll :: MonadCatch m => m a -> (SomeException -> m a) -> m a
+ Control.Monad.Catch: catchAll :: (HasCallStack, MonadCatch m) => m a -> (SomeException -> m a) -> m a
- Control.Monad.Catch: catchIOError :: MonadCatch m => m a -> (IOError -> m a) -> m a
+ Control.Monad.Catch: catchIOError :: (HasCallStack, MonadCatch m) => m a -> (IOError -> m a) -> m a
- Control.Monad.Catch: catchIf :: (MonadCatch m, Exception e) => (e -> Bool) -> m a -> (e -> m a) -> m a
+ Control.Monad.Catch: catchIf :: (HasCallStack, MonadCatch m, Exception e) => (e -> Bool) -> m a -> (e -> m a) -> m a
- Control.Monad.Catch: catchJust :: (MonadCatch m, Exception e) => (e -> Maybe b) -> m a -> (b -> m a) -> m a
+ Control.Monad.Catch: catchJust :: (HasCallStack, MonadCatch m, Exception e) => (e -> Maybe b) -> m a -> (b -> m a) -> m a
- Control.Monad.Catch: catches :: (Foldable f, MonadCatch m) => m a -> f (Handler m a) -> m a
+ Control.Monad.Catch: catches :: (HasCallStack, Foldable f, MonadCatch m) => m a -> f (Handler m a) -> m a
- Control.Monad.Catch: finally :: MonadMask m => m a -> m b -> m a
+ Control.Monad.Catch: finally :: (HasCallStack, MonadMask m) => m a -> m b -> m a
- Control.Monad.Catch: generalBracket :: MonadMask m => m a -> (a -> ExitCase b -> m c) -> (a -> m b) -> m (b, c)
+ Control.Monad.Catch: generalBracket :: (MonadMask m, HasCallStack) => m a -> (a -> ExitCase b -> m c) -> (a -> m b) -> m (b, c)
- Control.Monad.Catch: handle :: (MonadCatch m, Exception e) => (e -> m a) -> m a -> m a
+ Control.Monad.Catch: handle :: (HasCallStack, MonadCatch m, Exception e) => (e -> m a) -> m a -> m a
- Control.Monad.Catch: handleAll :: MonadCatch m => (SomeException -> m a) -> m a -> m a
+ Control.Monad.Catch: handleAll :: (HasCallStack, MonadCatch m) => (SomeException -> m a) -> m a -> m a
- Control.Monad.Catch: handleIOError :: MonadCatch m => (IOError -> m a) -> m a -> m a
+ Control.Monad.Catch: handleIOError :: (HasCallStack, MonadCatch m) => (IOError -> m a) -> m a -> m a
- Control.Monad.Catch: handleIf :: (MonadCatch m, Exception e) => (e -> Bool) -> (e -> m a) -> m a -> m a
+ Control.Monad.Catch: handleIf :: (HasCallStack, MonadCatch m, Exception e) => (e -> Bool) -> (e -> m a) -> m a -> m a
- Control.Monad.Catch: handleJust :: (MonadCatch m, Exception e) => (e -> Maybe b) -> (b -> m a) -> m a -> m a
+ Control.Monad.Catch: handleJust :: (HasCallStack, MonadCatch m, Exception e) => (e -> Maybe b) -> (b -> m a) -> m a -> m a
- Control.Monad.Catch: mask :: MonadMask m => ((forall a. m a -> m a) -> m b) -> m b
+ Control.Monad.Catch: mask :: (MonadMask m, HasCallStack) => ((forall a. m a -> m a) -> m b) -> m b
- Control.Monad.Catch: mask_ :: MonadMask m => m a -> m a
+ Control.Monad.Catch: mask_ :: (HasCallStack, MonadMask m) => m a -> m a
- Control.Monad.Catch: onError :: MonadMask m => m a -> m b -> m a
+ Control.Monad.Catch: onError :: (HasCallStack, MonadMask m) => m a -> m b -> m a
- Control.Monad.Catch: onException :: MonadCatch m => m a -> m b -> m a
+ Control.Monad.Catch: onException :: (HasCallStack, MonadCatch m) => m a -> m b -> m a
- Control.Monad.Catch: throwM :: (MonadThrow m, Exception e) => e -> m a
+ Control.Monad.Catch: throwM :: (MonadThrow m, HasCallStack, Exception e) => e -> m a
- Control.Monad.Catch: try :: (MonadCatch m, Exception e) => m a -> m (Either e a)
+ Control.Monad.Catch: try :: (HasCallStack, MonadCatch m, Exception e) => m a -> m (Either e a)
- Control.Monad.Catch: tryJust :: (MonadCatch m, Exception e) => (e -> Maybe b) -> m a -> m (Either b a)
+ Control.Monad.Catch: tryJust :: (HasCallStack, MonadCatch m, Exception e) => (e -> Maybe b) -> m a -> m (Either b a)
- Control.Monad.Catch: uninterruptibleMask :: MonadMask m => ((forall a. m a -> m a) -> m b) -> m b
+ Control.Monad.Catch: uninterruptibleMask :: (MonadMask m, HasCallStack) => ((forall a. m a -> m a) -> m b) -> m b
- Control.Monad.Catch: uninterruptibleMask_ :: MonadMask m => m a -> m a
+ Control.Monad.Catch: uninterruptibleMask_ :: (HasCallStack, MonadMask m) => m a -> m a

Files

.ghci view
@@ -1,1 +1,1 @@-:set -isrc -idist/build/autogen -optPdist/build/autogen/cabal_macros.h+:set -isrc -idist/build/autogen -optPdist/build/autogen/cabal_macros.h
.gitignore view
@@ -1,38 +1,38 @@-dist-dist-newstyle-docs-wiki-TAGS-tags-wip-.DS_Store-.*.swp-.*.swo-*.o-*.hi-*~-*#-.stack-work/-cabal-dev-*.chi-*.chs.h-*.dyn_o-*.dyn_hi-.hpc-.hsenv-.cabal-sandbox/-cabal.sandbox.config-*.prof-*.aux-*.hp-*.eventlog-cabal.project.local-cabal.project.local~-.HTF/-.ghc.environment.*--# GHC-dist-boot-dist-install-GNUmakefile-ghc.mk+dist
+dist-newstyle
+docs
+wiki
+TAGS
+tags
+wip
+.DS_Store
+.*.swp
+.*.swo
+*.o
+*.hi
+*~
+*#
+.stack-work/
+cabal-dev
+*.chi
+*.chs.h
+*.dyn_o
+*.dyn_hi
+.hpc
+.hsenv
+.cabal-sandbox/
+cabal.sandbox.config
+*.prof
+*.aux
+*.hp
+*.eventlog
+cabal.project.local
+cabal.project.local~
+.HTF/
+.ghc.environment.*
+
+# GHC
+dist-boot
+dist-install
+GNUmakefile
+ghc.mk
.vim.custom view
@@ -1,31 +1,31 @@-" Add the following to your .vimrc to automatically load this on startup--" if filereadable(".vim.custom")-"     so .vim.custom-" endif--function StripTrailingWhitespace()-  let myline=line(".")-  let mycolumn = col(".")-  silent %s/  *$//-  call cursor(myline, mycolumn)-endfunction--" enable syntax highlighting-syntax on--" search for the tags file anywhere between here and /-set tags=TAGS;/--" highlight tabs and trailing spaces-set listchars=tab:‗‗,trail:‗-set list--" f2 runs hasktags-map <F2> :exec ":!hasktags -x -c --ignore src"<CR><CR>--" strip trailing whitespace before saving-" au BufWritePre *.hs,*.markdown silent! cal StripTrailingWhitespace()--" rebuild hasktags after saving-au BufWritePost *.hs silent! :exec ":!hasktags -x -c --ignore src"+" Add the following to your .vimrc to automatically load this on startup
+
+" if filereadable(".vim.custom")
+"     so .vim.custom
+" endif
+
+function StripTrailingWhitespace()
+  let myline=line(".")
+  let mycolumn = col(".")
+  silent %s/  *$//
+  call cursor(myline, mycolumn)
+endfunction
+
+" enable syntax highlighting
+syntax on
+
+" search for the tags file anywhere between here and /
+set tags=TAGS;/
+
+" highlight tabs and trailing spaces
+set listchars=tab:‗‗,trail:‗
+set list
+
+" f2 runs hasktags
+map <F2> :exec ":!hasktags -x -c --ignore src"<CR><CR>
+
+" strip trailing whitespace before saving
+" au BufWritePre *.hs,*.markdown silent! cal StripTrailingWhitespace()
+
+" rebuild hasktags after saving
+au BufWritePost *.hs silent! :exec ":!hasktags -x -c --ignore src"
AUTHORS.markdown view
@@ -1,1 +1,1 @@-`exceptions` is based on code contributed by [Mark Lentzcner](http://github.com/mzero).+`exceptions` is based on code contributed by [Mark Lentzcner](http://github.com/mzero).
CHANGELOG.markdown view
@@ -1,118 +1,124 @@-0.10.5 [2022.05.07]---------------------* Allow building with `transformers-0.6.*` and `mtl-2.3.*`.--0.10.4 [2019.12.26]---------------------* Allow building with `template-haskell-2.16.*`.-* Only depend on `transformers-compat` on old versions of GHC.--0.10.3 [2019.08.27]---------------------* `MonadThrow` instance for the strict `ST` monad.--0.10.2 [2019.05.02]---------------------* Allow building with `base-4.13`/`template-haskell-2.15`.--0.10.1 [2019.03.26]---------------------* Define a `MonadFail` instance for `CatchT`.-* Allow `QuickCheck-2.13` in the test suite.--0.10.0--------* Fix a regression in 0.9.0 whereby the non-IO effects in `bracket`'s `use`-  action were not visible to the `release` action, and the non-IO effects in the-  `release` action were not visible after the `bracket` call.-* The type of `generalBracket` was changed in order to restore those non-IO-  effects, so if you are a library author that provides a `MonadMask` instance,-  you will need to update your implementation of this method.-* Add `MonadMask` instance for `MaybeT`-* Add `onError` function whose action also runs on errors which are not-  exceptions, such as a `Nothing` or a `Left`.--0.9.0-------* Add `generalBracket` to the `MonadMask` typeclass, allowing more-  valid instances.--  Note that functions such as `bracket` and `finally` are now based off of-  `generalBracket`, so if you are a library author that provides a `MonadMask`-  instance, you will need to provide an implementation of this method.-* Add `MonadMask` instances for `ExceptT` and `ErrorT`--0.8.3-------* `MonadCatch` and `MonadMask` instances for `Either SomeException`--0.8.1-------* Support for throwing in the `template-haskell` `Q` monad-* Support for `transformers` 0.5--0.8.0.1---------* Resolved warnings on GHC 7.10 and with transformers 0.4.--0.8-----* Use `transformers-compat` to allow support for `ExceptT` even on older `transformers` versions.--0.7-----* `stm` support--0.6-----* Split out `MonadMask`-* Added `transformers` 0.4 support--0.5-----* Added instances of `MonadThrow` for `ListT`, `MaybeT`, `ErrorT` and `ContT`.--0.4-----* Factored out a separate `MonadThrow`.--0.3.3.1---------* QuickCheck dependency bump--0.3.3-------* Relicensed under the 3-clause BSD license.--0.3.2-------* Better documentation for `CatchT`.-* Added `handle`-like analogues for parity with `Control.Exception`.--0.3.1-------* Fixed test suite.--0.3-----* Moved `CatchT` to `Control.Monad.Catch.Pure` to make it clear it isn't required for working with `IO`.--0.2.1-----* Added `mask_` and `uninterruptibleMask_` to `Control.Monad.Catch`.--0.2-----* Added `uninterruptibleMask` to `MonadCatch`.--0.1.1-------* Flagged `Control.Monad.Catch` as `Trustworthy`--0.1.0.1-------* License fix. We were accidentally listing both an APL and BSD3 license in the same module--0.1-----* Repository initialized+0.10.6 [2022.11.30]
+-------------------
+* The class methods and functions in `Control.Monad.Catch` now have
+  `HasCallStack` constraints.
+* Drop support for GHC 7.0 and 7.2.
+
+0.10.5 [2022.05.07]
+-------------------
+* Allow building with `transformers-0.6.*` and `mtl-2.3.*`.
+
+0.10.4 [2019.12.26]
+-------------------
+* Allow building with `template-haskell-2.16.*`.
+* Only depend on `transformers-compat` on old versions of GHC.
+
+0.10.3 [2019.08.27]
+-------------------
+* `MonadThrow` instance for the strict `ST` monad.
+
+0.10.2 [2019.05.02]
+-------------------
+* Allow building with `base-4.13`/`template-haskell-2.15`.
+
+0.10.1 [2019.03.26]
+-------------------
+* Define a `MonadFail` instance for `CatchT`.
+* Allow `QuickCheck-2.13` in the test suite.
+
+0.10.0
+------
+* Fix a regression in 0.9.0 whereby the non-IO effects in `bracket`'s `use`
+  action were not visible to the `release` action, and the non-IO effects in the
+  `release` action were not visible after the `bracket` call.
+* The type of `generalBracket` was changed in order to restore those non-IO
+  effects, so if you are a library author that provides a `MonadMask` instance,
+  you will need to update your implementation of this method.
+* Add `MonadMask` instance for `MaybeT`
+* Add `onError` function whose action also runs on errors which are not
+  exceptions, such as a `Nothing` or a `Left`.
+
+0.9.0
+-----
+* Add `generalBracket` to the `MonadMask` typeclass, allowing more
+  valid instances.
+
+  Note that functions such as `bracket` and `finally` are now based off of
+  `generalBracket`, so if you are a library author that provides a `MonadMask`
+  instance, you will need to provide an implementation of this method.
+* Add `MonadMask` instances for `ExceptT` and `ErrorT`
+
+0.8.3
+-----
+* `MonadCatch` and `MonadMask` instances for `Either SomeException`
+
+0.8.1
+-----
+* Support for throwing in the `template-haskell` `Q` monad
+* Support for `transformers` 0.5
+
+0.8.0.1
+-------
+* Resolved warnings on GHC 7.10 and with transformers 0.4.
+
+0.8
+---
+* Use `transformers-compat` to allow support for `ExceptT` even on older `transformers` versions.
+
+0.7
+---
+* `stm` support
+
+0.6
+---
+* Split out `MonadMask`
+* Added `transformers` 0.4 support
+
+0.5
+---
+* Added instances of `MonadThrow` for `ListT`, `MaybeT`, `ErrorT` and `ContT`.
+
+0.4
+---
+* Factored out a separate `MonadThrow`.
+
+0.3.3.1
+-------
+* QuickCheck dependency bump
+
+0.3.3
+-----
+* Relicensed under the 3-clause BSD license.
+
+0.3.2
+-----
+* Better documentation for `CatchT`.
+* Added `handle`-like analogues for parity with `Control.Exception`.
+
+0.3.1
+-----
+* Fixed test suite.
+
+0.3
+---
+* Moved `CatchT` to `Control.Monad.Catch.Pure` to make it clear it isn't required for working with `IO`.
+
+0.2.1
+---
+* Added `mask_` and `uninterruptibleMask_` to `Control.Monad.Catch`.
+
+0.2
+---
+* Added `uninterruptibleMask` to `MonadCatch`.
+
+0.1.1
+-----
+* Flagged `Control.Monad.Catch` as `Trustworthy`
+
+0.1.0.1
+-----
+* License fix. We were accidentally listing both an APL and BSD3 license in the same module
+
+0.1
+---
+* Repository initialized
LICENSE view
@@ -1,31 +1,31 @@-Copyright 2013-2015 Edward Kmett-Copyright 2012 Google Inc.--All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions-are met:--1. Redistributions of source code must retain the above copyright-   notice, this list of conditions and the following disclaimer.--2. Redistributions in binary form must reproduce the above copyright-   notice, this list of conditions and the following disclaimer in the-   documentation and/or other materials provided with the distribution.--3. Neither the name of the author nor the names of his contributors-   may be used to endorse or promote products derived from this software-   without specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE-DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,-STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN-ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE-POSSIBILITY OF SUCH DAMAGE.+Copyright 2013-2015 Edward Kmett
+Copyright 2012 Google Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the author nor the names of his contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
README.markdown view
@@ -1,15 +1,15 @@-exceptions-==========--[![Hackage](https://img.shields.io/hackage/v/exceptions.svg)](https://hackage.haskell.org/package/exceptions) [![Build Status](https://github.com/ekmett/exceptions/workflows/Haskell-CI/badge.svg)](https://github.com/ekmett/exceptions/actions?query=workflow%3AHaskell-CI)--This package provides (optionally pure) extensible exceptions that are compatible with the monad transformer library.--Contact Information----------------------Contributions and bug reports are welcome!--Please feel free to contact me through github or on the #haskell IRC channel on irc.freenode.net.---Edward Kmett+exceptions
+==========
+
+[![Hackage](https://img.shields.io/hackage/v/exceptions.svg)](https://hackage.haskell.org/package/exceptions) [![Build Status](https://github.com/ekmett/exceptions/workflows/Haskell-CI/badge.svg)](https://github.com/ekmett/exceptions/actions?query=workflow%3AHaskell-CI)
+
+This package provides (optionally pure) extensible exceptions that are compatible with the monad transformer library.
+
+Contact Information
+-------------------
+
+Contributions and bug reports are welcome!
+
+Please feel free to contact me through github or on the #haskell IRC channel on irc.freenode.net.
+
+-Edward Kmett
Setup.lhs view
@@ -1,7 +1,7 @@-#!/usr/bin/runhaskell-> module Main (main) where--> import Distribution.Simple--> main :: IO ()-> main = defaultMain+#!/usr/bin/runhaskell
+> module Main (main) where
+
+> import Distribution.Simple
+
+> main :: IO ()
+> main = defaultMain
exceptions.cabal view
@@ -1,97 +1,97 @@-name:          exceptions-category:      Control, Exceptions, Monad-version:       0.10.5-cabal-version: >= 1.10-license:       BSD3-license-file:  LICENSE-author:        Edward A. Kmett-maintainer:    Edward A. Kmett <ekmett@gmail.com>-stability:     provisional-homepage:      http://github.com/ekmett/exceptions/-bug-reports:   http://github.com/ekmett/exceptions/issues-copyright:     Copyright (C) 2013-2015 Edward A. Kmett-               Copyright (C) 2012 Google Inc.-build-type:    Simple-tested-with:   GHC == 7.0.4-             , GHC == 7.2.2-             , GHC == 7.4.2-             , GHC == 7.6.3-             , GHC == 7.8.4-             , GHC == 7.10.3-             , GHC == 8.0.2-             , GHC == 8.2.2-             , GHC == 8.4.4-             , GHC == 8.6.5-             , GHC == 8.8.4-             , GHC == 8.10.4-             , GHC == 9.0.1-synopsis:      Extensible optionally-pure exceptions-description:   Extensible optionally-pure exceptions.--extra-source-files:-  .ghci-  .gitignore-  .vim.custom-  AUTHORS.markdown-  README.markdown-  CHANGELOG.markdown--source-repository head-  type: git-  location: git://github.com/ekmett/exceptions.git--flag transformers-0-4-  description: Use @transformers-0.4@ or later.-  default:     True--library-  build-depends:-    base                       >= 4.3      && < 5,-    stm                        >= 2.2      && < 3,-    template-haskell           >= 2.2      && < 2.19,-    mtl                        >= 2.0      && < 2.4--  if !impl(ghc >= 8.0)-    build-depends: fail        == 4.9.*--  if flag(transformers-0-4)-    build-depends:-      transformers             >= 0.4      && < 0.7-  else-    build-depends:-      transformers             >= 0.2      && < 0.4,-      transformers-compat      >= 0.3      && < 0.8--  exposed-modules:-    Control.Monad.Catch-    Control.Monad.Catch.Pure--  ghc-options: -Wall -fwarn-tabs -O2-  hs-source-dirs: src-  default-language: Haskell2010--test-suite exceptions-tests-  main-is: Tests.hs-  other-modules: Control.Monad.Catch.Tests-  hs-source-dirs: tests-  ghc-options: -Wall -fwarn-tabs-  default-language: Haskell2010-  type: exitcode-stdio-1.0-  build-depends:-    base,-    exceptions,-    stm,-    template-haskell,-    mtl                        >= 2.0,-    test-framework             >= 0.8      && < 0.9,-    test-framework-hunit       >= 0.3      && < 0.4,-    test-framework-quickcheck2 >= 0.3      && < 0.4,-    QuickCheck                 >= 2.5      && < 2.15--  if flag(transformers-0-4)-    build-depends:-      transformers             >= 0.4      && < 0.7-  else-    build-depends:-      transformers             >= 0.2      && < 0.4,-      transformers-compat      >= 0.3      && < 0.8+name:          exceptions
+category:      Control, Exceptions, Monad
+version:       0.10.6
+cabal-version: >= 1.10
+license:       BSD3
+license-file:  LICENSE
+author:        Edward A. Kmett
+maintainer:    Edward A. Kmett <ekmett@gmail.com>
+stability:     provisional
+homepage:      http://github.com/ekmett/exceptions/
+bug-reports:   http://github.com/ekmett/exceptions/issues
+copyright:     Copyright (C) 2013-2015 Edward A. Kmett
+               Copyright (C) 2012 Google Inc.
+build-type:    Simple
+tested-with:   GHC == 7.4.2
+             , GHC == 7.6.3
+             , GHC == 7.8.4
+             , GHC == 7.10.3
+             , GHC == 8.0.2
+             , GHC == 8.2.2
+             , GHC == 8.4.4
+             , GHC == 8.6.5
+             , GHC == 8.8.4
+             , GHC == 8.10.7
+             , GHC == 9.0.2
+             , GHC == 9.2.2
+synopsis:      Extensible optionally-pure exceptions
+description:   Extensible optionally-pure exceptions.
+
+extra-source-files:
+  .ghci
+  .gitignore
+  .vim.custom
+  AUTHORS.markdown
+  README.markdown
+  CHANGELOG.markdown
+
+source-repository head
+  type: git
+  location: git://github.com/ekmett/exceptions.git
+
+flag transformers-0-4
+  description: Use @transformers-0.4@ or later.
+  default:     True
+
+library
+  build-depends:
+    base                       >= 4.5      && < 5,
+    stm                        >= 2.2      && < 3,
+    template-haskell           >= 2.7      && < 2.20,
+    mtl                        >= 2.0      && < 2.4
+
+  if !impl(ghc >= 8.0)
+    build-depends: call-stack  >= 0.1      && < 0.5,
+                   fail        == 4.9.*
+
+  if flag(transformers-0-4)
+    build-depends:
+      transformers             >= 0.4      && < 0.7
+  else
+    build-depends:
+      transformers             >= 0.2      && < 0.4,
+      transformers-compat      >= 0.3      && < 0.8
+
+  exposed-modules:
+    Control.Monad.Catch
+    Control.Monad.Catch.Pure
+
+  ghc-options: -Wall -fwarn-tabs -O2
+  hs-source-dirs: src
+  default-language: Haskell2010
+
+test-suite exceptions-tests
+  main-is: Tests.hs
+  other-modules: Control.Monad.Catch.Tests
+  hs-source-dirs: tests
+  ghc-options: -Wall -fwarn-tabs
+  default-language: Haskell2010
+  type: exitcode-stdio-1.0
+  build-depends:
+    base,
+    exceptions,
+    stm,
+    template-haskell,
+    mtl                        >= 2.0,
+    test-framework             >= 0.8      && < 0.9,
+    test-framework-hunit       >= 0.3      && < 0.4,
+    test-framework-quickcheck2 >= 0.3      && < 0.4,
+    QuickCheck                 >= 2.5      && < 2.15
+
+  if flag(transformers-0-4)
+    build-depends:
+      transformers             >= 0.4      && < 0.7
+  else
+    build-depends:
+      transformers             >= 0.2      && < 0.4,
+      transformers-compat      >= 0.3      && < 0.8
src/Control/Monad/Catch.hs view
@@ -1,877 +1,891 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}--#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702-{-# LANGUAGE Trustworthy #-}-#endif--#ifndef MIN_VERSION_transformers-#define MIN_VERSION_transformers(x,y,z) 1-#endif--#if !(MIN_VERSION_transformers(0,6,0))-{-# OPTIONS_GHC -fno-warn-deprecations #-}-#endif------------------------------------------------------------------------ |--- Copyright   :  (C) Edward Kmett 2013-2015, (c) Google Inc. 2012--- License     :  BSD-style (see the file LICENSE)--- Maintainer  :  Edward Kmett <ekmett@gmail.com>--- Stability   :  experimental--- Portability :  non-portable------ This module supports monads that can throw extensible exceptions. The--- exceptions are the very same from "Control.Exception", and the operations--- offered very similar, but here they are not limited to 'IO'.------ This code is in the style of both transformers and mtl, and is compatible--- with them, though doesn't mimic the module structure or offer the complete--- range of features in those packages.------ This is very similar to 'ErrorT' and 'MonadError', but based on features of--- "Control.Exception". In particular, it handles the complex case of--- asynchronous exceptions by including 'mask' in the typeclass. Note that the--- extensible exceptions feature relies on the RankNTypes language extension.-----------------------------------------------------------------------module Control.Monad.Catch (-    -- * Typeclass-    -- $mtl-    MonadThrow(..)-  , MonadCatch(..)-  , MonadMask(..)-  , ExitCase(..)--    -- * Utilities-    -- $utilities-  , mask_-  , uninterruptibleMask_-  , catchAll-  , catchIOError-  , catchJust-  , catchIf-  , Handler(..), catches-  , handle-  , handleAll-  , handleIOError-  , handleJust-  , handleIf-  , try-  , tryJust-  , onException-  , onError-  , bracket-  , bracket_-  , finally-  , bracketOnError-    -- * Re-exports from Control.Exception-  , Exception(..)-  , SomeException(..)-  ) where--import Control.Exception (Exception(..), SomeException(..))-import qualified Control.Exception as ControlException-import Control.Monad (liftM)-import qualified Control.Monad.STM as STM-import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS-import qualified Control.Monad.Trans.RWS.Strict as StrictRWS-import qualified Control.Monad.Trans.State.Lazy as LazyS-import qualified Control.Monad.Trans.State.Strict as StrictS-import qualified Control.Monad.Trans.Writer.Lazy as LazyW-import qualified Control.Monad.Trans.Writer.Strict as StrictW-import Control.Monad.ST (ST)-import Control.Monad.STM (STM)-import Control.Monad.Trans.Class (MonadTrans(..))-import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)-import Control.Monad.Trans.Except (ExceptT(..), runExceptT)-import Control.Monad.Trans.Cont (ContT)-import Control.Monad.Trans.Identity-import Control.Monad.Trans.Reader (ReaderT(..), runReaderT)--import Language.Haskell.TH.Syntax (Q)--#if MIN_VERSION_base(4,4,0)-import Control.Monad.ST.Unsafe (unsafeIOToST)-#else-import Control.Monad.ST (unsafeIOToST)-#endif--#if __GLASGOW_HASKELL__ < 706-import Prelude hiding (catch, foldr)-import Data.Foldable-import Data.Monoid-#elif __GLASGOW_HASKELL__ < 710-import Prelude hiding (foldr)-import Data.Foldable-import Data.Monoid-#endif--#if __GLASGOW_HASKELL__ < 710-import Control.Applicative-#endif--#if !(MIN_VERSION_transformers(0,6,0))-import Control.Monad.Trans.Error (ErrorT(..), Error, runErrorT)-import Control.Monad.Trans.List (ListT(..), runListT)-#endif----------------------------------------------------------------------------------- $mtl--- The mtl style typeclass----------------------------------------------------------------------------------- | A class for monads in which exceptions may be thrown.------ Instances should obey the following law:------ > throwM e >> x = throwM e------ In other words, throwing an exception short-circuits the rest of the monadic--- computation.-class Monad m => MonadThrow m where-  -- | Throw an exception. Note that this throws when this action is run in-  -- the monad @m@, not when it is applied. It is a generalization of-  -- "Control.Exception"'s 'ControlException.throwIO'.-  ---  -- Should satisfy the law:-  ---  -- > throwM e >> f = throwM e-  throwM :: Exception e => e -> m a---- | A class for monads which allow exceptions to be caught, in particular--- exceptions which were thrown by 'throwM'.------ Instances should obey the following law:------ > catch (throwM e) f = f e------ Note that the ability to catch an exception does /not/ guarantee that we can--- deal with all possible exit points from a computation. Some monads, such as--- continuation-based stacks, allow for more than just a success/failure--- strategy, and therefore @catch@ /cannot/ be used by those monads to properly--- implement a function such as @finally@. For more information, see--- 'MonadMask'.-class MonadThrow m => MonadCatch m where-  -- | Provide a handler for exceptions thrown during execution of the first-  -- action. Note that type of the type of the argument to the handler will-  -- constrain which exceptions are caught. See "Control.Exception"'s-  -- 'ControlException.catch'.-  catch :: Exception e => m a -> (e -> m a) -> m a---- | A class for monads which provide for the ability to account for--- all possible exit points from a computation, and to mask--- asynchronous exceptions. Continuation-based monads are invalid--- instances of this class.------ Instances should ensure that, in the following code:------ > fg = f `finally` g------ The action @g@ is called regardless of what occurs within @f@, including--- async exceptions. Some monads allow @f@ to abort the computation via other--- effects than throwing an exception. For simplicity, we will consider aborting--- and throwing an exception to be two forms of "throwing an error".------ If @f@ and @g@ both throw an error, the error thrown by @fg@ depends on which--- errors we're talking about. In a monad transformer stack, the deeper layers--- override the effects of the inner layers; for example, @ExceptT e1 (Except--- e2) a@ represents a value of type @Either e2 (Either e1 a)@, so throwing both--- an @e1@ and an @e2@ will result in @Left e2@. If @f@ and @g@ both throw an--- error from the same layer, instances should ensure that the error from @g@--- wins.------ Effects other than throwing an error are also overridden by the deeper layers.--- For example, @StateT s Maybe a@ represents a value of type @s -> Maybe (a,--- s)@, so if an error thrown from @f@ causes this function to return @Nothing@,--- any changes to the state which @f@ also performed will be erased. As a--- result, @g@ will see the state as it was before @f@. Once @g@ completes,--- @f@'s error will be rethrown, so @g@' state changes will be erased as well.--- This is the normal interaction between effects in a monad transformer stack.------ By contrast, <https://hackage.haskell.org/package/lifted-base lifted-base>'s--- version of 'finally' always discards all of @g@'s non-IO effects, and @g@--- never sees any of @f@'s non-IO effects, regardless of the layer ordering and--- regardless of whether @f@ throws an error. This is not the result of--- interacting effects, but a consequence of @MonadBaseControl@'s approach.-class MonadCatch m => MonadMask m where-  -- | Runs an action with asynchronous exceptions disabled. The action is-  -- provided a method for restoring the async. environment to what it was-  -- at the 'mask' call. See "Control.Exception"'s 'ControlException.mask'.-  mask :: ((forall a. m a -> m a) -> m b) -> m b--  -- | Like 'mask', but the masked computation is not interruptible (see-  -- "Control.Exception"'s 'ControlException.uninterruptibleMask'. WARNING:-  -- Only use if you need to mask exceptions around an interruptible operation-  -- AND you can guarantee the interruptible operation will only block for a-  -- short period of time. Otherwise you render the program/thread unresponsive-  -- and/or unkillable.-  uninterruptibleMask :: ((forall a. m a -> m a) -> m b) -> m b--  -- | A generalized version of 'bracket' which uses 'ExitCase' to distinguish-  -- the different exit cases, and returns the values of both the 'use' and-  -- 'release' actions. In practice, this extra information is rarely needed,-  -- so it is often more convenient to use one of the simpler functions which-  -- are defined in terms of this one, such as 'bracket', 'finally', 'onError',-  -- and 'bracketOnError'.-  ---  -- This function exists because in order to thread their effects through the-  -- execution of 'bracket', monad transformers need values to be threaded from-  -- 'use' to 'release' and from 'release' to the output value.-  ---  -- /NOTE/ This method was added in version 0.9.0 of this-  -- library. Previously, implementation of functions like 'bracket'-  -- and 'finally' in this module were based on the 'mask' and-  -- 'uninterruptibleMask' functions only, disallowing some classes of-  -- tranformers from having @MonadMask@ instances (notably-  -- multi-exit-point transformers like 'ExceptT'). If you are a-  -- library author, you'll now need to provide an implementation for-  -- this method. The @StateT@ implementation demonstrates most of the-  -- subtleties:-  ---  -- @-  -- generalBracket acquire release use = StateT $ \s0 -> do-  --   ((b, _s2), (c, s3)) <- generalBracket-  --     (runStateT acquire s0)-  --     (\(resource, s1) exitCase -> case exitCase of-  --       ExitCaseSuccess (b, s2) -> runStateT (release resource (ExitCaseSuccess b)) s2-  ---  --       -- In the two other cases, the base monad overrides @use@'s state-  --       -- changes and the state reverts to @s1@.-  --       ExitCaseException e     -> runStateT (release resource (ExitCaseException e)) s1-  --       ExitCaseAbort           -> runStateT (release resource ExitCaseAbort) s1-  --     )-  --     (\(resource, s1) -> runStateT (use resource) s1)-  --   return ((b, c), s3)-  -- @-  ---  -- The @StateT s m@ implementation of @generalBracket@ delegates to the @m@-  -- implementation of @generalBracket@. The @acquire@, @use@, and @release@-  -- arguments given to @StateT@'s implementation produce actions of type-  -- @StateT s m a@, @StateT s m b@, and @StateT s m c@. In order to run those-  -- actions in the base monad, we need to call @runStateT@, from which we-  -- obtain actions of type @m (a, s)@, @m (b, s)@, and @m (c, s)@. Since each-  -- action produces the next state, it is important to feed the state produced-  -- by the previous action to the next action.-  ---  -- In the 'ExitCaseSuccess' case, the state starts at @s0@, flows through-  -- @acquire@ to become @s1@, flows through @use@ to become @s2@, and finally-  -- flows through @release@ to become @s3@. In the other two cases, @release@-  -- does not receive the value @s2@, so its action cannot see the state changes-  -- performed by @use@. This is fine, because in those two cases, an error was-  -- thrown in the base monad, so as per the usual interaction between effects-  -- in a monad transformer stack, those state changes get reverted. So we start-  -- from @s1@ instead.-  ---  -- Finally, the @m@ implementation of @generalBracket@ returns the pairs-  -- @(b, s)@ and @(c, s)@. For monad transformers other than @StateT@, this-  -- will be some other type representing the effects and values performed and-  -- returned by the @use@ and @release@ actions. The effect part of the @use@-  -- result, in this case @_s2@, usually needs to be discarded, since those-  -- effects have already been incorporated in the @release@ action.-  ---  -- The only effect which is intentionally not incorporated in the @release@-  -- action is the effect of throwing an error. In that case, the error must be-  -- re-thrown. One subtlety which is easy to miss is that in the case in which-  -- @use@ and @release@ both throw an error, the error from @release@ should-  -- take priority. Here is an implementation for @ExceptT@ which demonstrates-  -- how to do this.-  ---  -- @-  -- generalBracket acquire release use = ExceptT $ do-  --   (eb, ec) <- generalBracket-  --     (runExceptT acquire)-  --     (\eresource exitCase -> case eresource of-  --       Left e -> return (Left e) -- nothing to release, acquire didn't succeed-  --       Right resource -> case exitCase of-  --         ExitCaseSuccess (Right b) -> runExceptT (release resource (ExitCaseSuccess b))-  --         ExitCaseException e       -> runExceptT (release resource (ExitCaseException e))-  --         _                         -> runExceptT (release resource ExitCaseAbort))-  --     (either (return . Left) (runExceptT . use))-  --   return $ do-  --     -- The order in which we perform those two 'Either' effects determines-  --     -- which error will win if they are both 'Left's. We want the error from-  --     -- 'release' to win.-  --     c <- ec-  --     b <- eb-  --     return (b, c)-  -- @-  ---  -- @since 0.9.0-  generalBracket-    :: m a-    -- ^ acquire some resource-    -> (a -> ExitCase b -> m c)-    -- ^ release the resource, observing the outcome of the inner action-    -> (a -> m b)-    -- ^ inner action to perform with the resource-    -> m (b, c)---- | A 'MonadMask' computation may either succeed with a value, abort with an--- exception, or abort for some other reason. For example, in @ExceptT e IO@--- you can use 'throwM' to abort with an exception ('ExitCaseException') or--- 'Control.Monad.Trans.Except.throwE' to abort with a value of type 'e'--- ('ExitCaseAbort').-data ExitCase a-  = ExitCaseSuccess a-  | ExitCaseException SomeException-  | ExitCaseAbort-  deriving Show--instance MonadThrow [] where-  throwM _ = []-instance MonadThrow Maybe where-  throwM _ = Nothing-instance MonadThrow Q where-  throwM = fail . show--instance MonadThrow IO where-  throwM = ControlException.throwIO-instance MonadCatch IO where-  catch = ControlException.catch-instance MonadMask IO where-  mask = ControlException.mask-  uninterruptibleMask = ControlException.uninterruptibleMask-  generalBracket acquire release use = mask $ \unmasked -> do-    resource <- acquire-    b <- unmasked (use resource) `catch` \e -> do-      _ <- release resource (ExitCaseException e)-      throwM e-    c <- release resource (ExitCaseSuccess b)-    return (b, c)--instance MonadThrow (ST s) where-  throwM = unsafeIOToST . ControlException.throwIO--instance MonadThrow STM where-  throwM = STM.throwSTM-instance MonadCatch STM where-  catch = STM.catchSTM--instance e ~ SomeException => MonadThrow (Either e) where-  throwM = Left . toException--- | @since 0.8.3-instance e ~ SomeException => MonadCatch (Either e) where-  catch (Left e) f =-    case fromException e of-      Nothing -> Left e-      Just e' -> f e'-  catch x@(Right _) _ = x--- | @since 0.8.3-instance e ~ SomeException => MonadMask (Either e) where-  mask f = f id-  uninterruptibleMask f = f id--  generalBracket acquire release use =-    case acquire of-      Left e -> Left e-      Right resource ->-        case use resource of-          Left e -> release resource (ExitCaseException e) >> Left e-          Right b -> do-            c <- release resource (ExitCaseSuccess b)-            return (b, c)--instance MonadThrow m => MonadThrow (IdentityT m) where-  throwM e = lift $ throwM e-instance MonadCatch m => MonadCatch (IdentityT m) where-  catch (IdentityT m) f = IdentityT (catch m (runIdentityT . f))-instance MonadMask m => MonadMask (IdentityT m) where-  mask a = IdentityT $ mask $ \u -> runIdentityT (a $ q u)-    where q :: (m a -> m a) -> IdentityT m a -> IdentityT m a-          q u = IdentityT . u . runIdentityT-  uninterruptibleMask a =-    IdentityT $ uninterruptibleMask $ \u -> runIdentityT (a $ q u)-      where q :: (m a -> m a) -> IdentityT m a -> IdentityT m a-            q u = IdentityT . u . runIdentityT--  generalBracket acquire release use = IdentityT $-    generalBracket-      (runIdentityT acquire)-      (\resource exitCase -> runIdentityT (release resource exitCase))-      (\resource -> runIdentityT (use resource))--instance MonadThrow m => MonadThrow (LazyS.StateT s m) where-  throwM e = lift $ throwM e-instance MonadCatch m => MonadCatch (LazyS.StateT s m) where-  catch = LazyS.liftCatch catch-instance MonadMask m => MonadMask (LazyS.StateT s m) where-  mask a = LazyS.StateT $ \s -> mask $ \u -> LazyS.runStateT (a $ q u) s-    where q :: (m (a, s) -> m (a, s)) -> LazyS.StateT s m a -> LazyS.StateT s m a-          q u (LazyS.StateT b) = LazyS.StateT (u . b)-  uninterruptibleMask a =-    LazyS.StateT $ \s -> uninterruptibleMask $ \u -> LazyS.runStateT (a $ q u) s-      where q :: (m (a, s) -> m (a, s)) -> LazyS.StateT s m a -> LazyS.StateT s m a-            q u (LazyS.StateT b) = LazyS.StateT (u . b)--  generalBracket acquire release use = LazyS.StateT $ \s0 -> do-    -- This implementation is given as an example in the documentation of-    -- 'generalBracket', so when changing it, remember to update the-    -- documentation's copy as well-    ((b, _s2), (c, s3)) <- generalBracket-      (LazyS.runStateT acquire s0)-      (\(resource, s1) exitCase -> case exitCase of-        ExitCaseSuccess (b, s2) -> LazyS.runStateT (release resource (ExitCaseSuccess b)) s2-        -- In the two other cases, the base monad overrides @use@'s state-        -- changes and the state reverts to @s1@.-        ExitCaseException e     -> LazyS.runStateT (release resource (ExitCaseException e)) s1-        ExitCaseAbort           -> LazyS.runStateT (release resource ExitCaseAbort) s1)-      (\(resource, s1) -> LazyS.runStateT (use resource) s1)-    return ((b, c), s3)--instance MonadThrow m => MonadThrow (StrictS.StateT s m) where-  throwM e = lift $ throwM e-instance MonadCatch m => MonadCatch (StrictS.StateT s m) where-  catch = StrictS.liftCatch catch-instance MonadMask m => MonadMask (StrictS.StateT s m) where-  mask a = StrictS.StateT $ \s -> mask $ \u -> StrictS.runStateT (a $ q u) s-    where q :: (m (a, s) -> m (a, s)) -> StrictS.StateT s m a -> StrictS.StateT s m a-          q u (StrictS.StateT b) = StrictS.StateT (u . b)-  uninterruptibleMask a =-    StrictS.StateT $ \s -> uninterruptibleMask $ \u -> StrictS.runStateT (a $ q u) s-      where q :: (m (a, s) -> m (a, s)) -> StrictS.StateT s m a -> StrictS.StateT s m a-            q u (StrictS.StateT b) = StrictS.StateT (u . b)--  generalBracket acquire release use = StrictS.StateT $ \s0 -> do-    ((b, _s2), (c, s3)) <- generalBracket-      (StrictS.runStateT acquire s0)-      (\(resource, s1) exitCase -> case exitCase of-        ExitCaseSuccess (b, s2) -> StrictS.runStateT (release resource (ExitCaseSuccess b)) s2-        -- In the two other cases, the base monad overrides @use@'s state-        -- changes and the state reverts to @s1@.-        ExitCaseException e     -> StrictS.runStateT (release resource (ExitCaseException e)) s1-        ExitCaseAbort           -> StrictS.runStateT (release resource ExitCaseAbort) s1)-      (\(resource, s1) -> StrictS.runStateT (use resource) s1)-    return ((b, c), s3)--instance MonadThrow m => MonadThrow (ReaderT r m) where-  throwM e = lift $ throwM e-instance MonadCatch m => MonadCatch (ReaderT r m) where-  catch (ReaderT m) c = ReaderT $ \r -> m r `catch` \e -> runReaderT (c e) r-instance MonadMask m => MonadMask (ReaderT r m) where-  mask a = ReaderT $ \e -> mask $ \u -> runReaderT (a $ q u) e-    where q :: (m a -> m a) -> ReaderT e m a -> ReaderT e m a-          q u (ReaderT b) = ReaderT (u . b)-  uninterruptibleMask a =-    ReaderT $ \e -> uninterruptibleMask $ \u -> runReaderT (a $ q u) e-      where q :: (m a -> m a) -> ReaderT e m a -> ReaderT e m a-            q u (ReaderT b) = ReaderT (u . b)--  generalBracket acquire release use = ReaderT $ \r ->-    generalBracket-      (runReaderT acquire r)-      (\resource exitCase -> runReaderT (release resource exitCase) r)-      (\resource -> runReaderT (use resource) r)--instance (MonadThrow m, Monoid w) => MonadThrow (StrictW.WriterT w m) where-  throwM e = lift $ throwM e-instance (MonadCatch m, Monoid w) => MonadCatch (StrictW.WriterT w m) where-  catch (StrictW.WriterT m) h = StrictW.WriterT $ m `catch ` \e -> StrictW.runWriterT (h e)-instance (MonadMask m, Monoid w) => MonadMask (StrictW.WriterT w m) where-  mask a = StrictW.WriterT $ mask $ \u -> StrictW.runWriterT (a $ q u)-    where q :: (m (a, w) -> m (a, w)) -> StrictW.WriterT w m a -> StrictW.WriterT w m a-          q u b = StrictW.WriterT $ u (StrictW.runWriterT b)-  uninterruptibleMask a =-    StrictW.WriterT $ uninterruptibleMask $ \u -> StrictW.runWriterT (a $ q u)-      where q :: (m (a, w) -> m (a, w)) -> StrictW.WriterT w m a -> StrictW.WriterT w m a-            q u b = StrictW.WriterT $ u (StrictW.runWriterT b)--  generalBracket acquire release use = StrictW.WriterT $ do-    ((b, _w12), (c, w123)) <- generalBracket-      (StrictW.runWriterT acquire)-      (\(resource, w1) exitCase -> case exitCase of-        ExitCaseSuccess (b, w12) -> do-          (c, w3) <- StrictW.runWriterT (release resource (ExitCaseSuccess b))-          return (c, mappend w12 w3)-        -- In the two other cases, the base monad overrides @use@'s state-        -- changes and the state reverts to @w1@.-        ExitCaseException e -> do-          (c, w3) <- StrictW.runWriterT (release resource (ExitCaseException e))-          return (c, mappend w1 w3)-        ExitCaseAbort -> do-          (c, w3) <- StrictW.runWriterT (release resource ExitCaseAbort)-          return (c, mappend w1 w3))-      (\(resource, w1) -> do-        (a, w2) <- StrictW.runWriterT (use resource)-        return (a, mappend w1 w2))-    return ((b, c), w123)--instance (MonadThrow m, Monoid w) => MonadThrow (LazyW.WriterT w m) where-  throwM e = lift $ throwM e-instance (MonadCatch m, Monoid w) => MonadCatch (LazyW.WriterT w m) where-  catch (LazyW.WriterT m) h = LazyW.WriterT $ m `catch ` \e -> LazyW.runWriterT (h e)-instance (MonadMask m, Monoid w) => MonadMask (LazyW.WriterT w m) where-  mask a = LazyW.WriterT $ mask $ \u -> LazyW.runWriterT (a $ q u)-    where q :: (m (a, w) -> m (a, w)) -> LazyW.WriterT w m a -> LazyW.WriterT w m a-          q u b = LazyW.WriterT $ u (LazyW.runWriterT b)-  uninterruptibleMask a =-    LazyW.WriterT $ uninterruptibleMask $ \u -> LazyW.runWriterT (a $ q u)-      where q :: (m (a, w) -> m (a, w)) -> LazyW.WriterT w m a -> LazyW.WriterT w m a-            q u b = LazyW.WriterT $ u (LazyW.runWriterT b)--  generalBracket acquire release use = LazyW.WriterT $ do-    ((b, _w12), (c, w123)) <- generalBracket-      (LazyW.runWriterT acquire)-      (\(resource, w1) exitCase -> case exitCase of-        ExitCaseSuccess (b, w12) -> do-          (c, w3) <- LazyW.runWriterT (release resource (ExitCaseSuccess b))-          return (c, mappend w12 w3)-        -- In the two other cases, the base monad overrides @use@'s state-        -- changes and the state reverts to @w1@.-        ExitCaseException e -> do-          (c, w3) <- LazyW.runWriterT (release resource (ExitCaseException e))-          return (c, mappend w1 w3)-        ExitCaseAbort -> do-          (c, w3) <- LazyW.runWriterT (release resource ExitCaseAbort)-          return (c, mappend w1 w3))-      (\(resource, w1) -> do-        (a, w2) <- LazyW.runWriterT (use resource)-        return (a, mappend w1 w2))-    return ((b, c), w123)--instance (MonadThrow m, Monoid w) => MonadThrow (LazyRWS.RWST r w s m) where-  throwM e = lift $ throwM e-instance (MonadCatch m, Monoid w) => MonadCatch (LazyRWS.RWST r w s m) where-  catch (LazyRWS.RWST m) h = LazyRWS.RWST $ \r s -> m r s `catch` \e -> LazyRWS.runRWST (h e) r s-instance (MonadMask m, Monoid w) => MonadMask (LazyRWS.RWST r w s m) where-  mask a = LazyRWS.RWST $ \r s -> mask $ \u -> LazyRWS.runRWST (a $ q u) r s-    where q :: (m (a, s, w) -> m (a, s, w)) -> LazyRWS.RWST r w s m a -> LazyRWS.RWST r w s m a-          q u (LazyRWS.RWST b) = LazyRWS.RWST $ \ r s -> u (b r s)-  uninterruptibleMask a =-    LazyRWS.RWST $ \r s -> uninterruptibleMask $ \u -> LazyRWS.runRWST (a $ q u) r s-      where q :: (m (a, s, w) -> m (a, s, w)) -> LazyRWS.RWST r w s m a -> LazyRWS.RWST r w s m a-            q u (LazyRWS.RWST b) = LazyRWS.RWST $ \ r s -> u (b r s)--  generalBracket acquire release use = LazyRWS.RWST $ \r s0 -> do-    ((b, _s2, _w12), (c, s3, w123)) <- generalBracket-      (LazyRWS.runRWST acquire r s0)-      (\(resource, s1, w1) exitCase -> case exitCase of-        ExitCaseSuccess (b, s2, w12) -> do-          (c, s3, w3) <- LazyRWS.runRWST (release resource (ExitCaseSuccess b)) r s2-          return (c, s3, mappend w12 w3)-        -- In the two other cases, the base monad overrides @use@'s state-        -- changes and the state reverts to @s1@ and @w1@.-        ExitCaseException e -> do-          (c, s3, w3) <- LazyRWS.runRWST (release resource (ExitCaseException e)) r s1-          return (c, s3, mappend w1 w3)-        ExitCaseAbort -> do-          (c, s3, w3) <- LazyRWS.runRWST (release resource ExitCaseAbort) r s1-          return (c, s3, mappend w1 w3))-      (\(resource, s1, w1) -> do-        (a, s2, w2) <- LazyRWS.runRWST (use resource) r s1-        return (a, s2, mappend w1 w2))-    return ((b, c), s3, w123)--instance (MonadThrow m, Monoid w) => MonadThrow (StrictRWS.RWST r w s m) where-  throwM e = lift $ throwM e-instance (MonadCatch m, Monoid w) => MonadCatch (StrictRWS.RWST r w s m) where-  catch (StrictRWS.RWST m) h = StrictRWS.RWST $ \r s -> m r s `catch` \e -> StrictRWS.runRWST (h e) r s-instance (MonadMask m, Monoid w) => MonadMask (StrictRWS.RWST r w s m) where-  mask a = StrictRWS.RWST $ \r s -> mask $ \u -> StrictRWS.runRWST (a $ q u) r s-    where q :: (m (a, s, w) -> m (a, s, w)) -> StrictRWS.RWST r w s m a -> StrictRWS.RWST r w s m a-          q u (StrictRWS.RWST b) = StrictRWS.RWST $ \ r s -> u (b r s)-  uninterruptibleMask a =-    StrictRWS.RWST $ \r s -> uninterruptibleMask $ \u -> StrictRWS.runRWST (a $ q u) r s-      where q :: (m (a, s, w) -> m (a, s, w)) -> StrictRWS.RWST r w s m a -> StrictRWS.RWST r w s m a-            q u (StrictRWS.RWST b) = StrictRWS.RWST $ \ r s -> u (b r s)--  generalBracket acquire release use = StrictRWS.RWST $ \r s0 -> do-    ((b, _s2, _w12), (c, s3, w123)) <- generalBracket-      (StrictRWS.runRWST acquire r s0)-      (\(resource, s1, w1) exitCase -> case exitCase of-        ExitCaseSuccess (b, s2, w12) -> do-          (c, s3, w3) <- StrictRWS.runRWST (release resource (ExitCaseSuccess b)) r s2-          return (c, s3, mappend w12 w3)-        -- In the two other cases, the base monad overrides @use@'s state-        -- changes and the state reverts to @s1@ and @w1@.-        ExitCaseException e -> do-          (c, s3, w3) <- StrictRWS.runRWST (release resource (ExitCaseException e)) r s1-          return (c, s3, mappend w1 w3)-        ExitCaseAbort -> do-          (c, s3, w3) <- StrictRWS.runRWST (release resource ExitCaseAbort) r s1-          return (c, s3, mappend w1 w3))-      (\(resource, s1, w1) -> do-        (a, s2, w2) <- StrictRWS.runRWST (use resource) r s1-        return (a, s2, mappend w1 w2))-    return ((b, c), s3, w123)---- | Throws exceptions into the base monad.-instance MonadThrow m => MonadThrow (MaybeT m) where-  throwM = lift . throwM--- | Catches exceptions from the base monad.-instance MonadCatch m => MonadCatch (MaybeT m) where-  catch (MaybeT m) f = MaybeT $ catch m (runMaybeT . f)--- | @since 0.10.0-instance MonadMask m => MonadMask (MaybeT m) where-  mask f = MaybeT $ mask $ \u -> runMaybeT $ f (q u)-    where-      q :: (m (Maybe a) -> m (Maybe a))-        -> MaybeT m a -> MaybeT m a-      q u (MaybeT b) = MaybeT (u b)-  uninterruptibleMask f = MaybeT $ uninterruptibleMask $ \u -> runMaybeT $ f (q u)-    where-      q :: (m (Maybe a) -> m (Maybe a))-        -> MaybeT m a -> MaybeT m a-      q u (MaybeT b) = MaybeT (u b)--  generalBracket acquire release use = MaybeT $ do-    (eb, ec) <- generalBracket-      (runMaybeT acquire)-      (\resourceMay exitCase -> case resourceMay of-        Nothing -> return Nothing -- nothing to release, acquire didn't succeed-        Just resource -> case exitCase of-          ExitCaseSuccess (Just b) -> runMaybeT (release resource (ExitCaseSuccess b))-          ExitCaseException e      -> runMaybeT (release resource (ExitCaseException e))-          _                        -> runMaybeT (release resource ExitCaseAbort))-      (\resourceMay -> case resourceMay of-        Nothing -> return Nothing-        Just resource -> runMaybeT (use resource))-    -- The order in which we perform those two 'Maybe' effects doesn't matter,-    -- since the error message is the same regardless.-    return ((,) <$> eb <*> ec)---- | Throws exceptions into the base monad.-instance MonadThrow m => MonadThrow (ExceptT e m) where-  throwM = lift . throwM--- | Catches exceptions from the base monad.-instance MonadCatch m => MonadCatch (ExceptT e m) where-  catch (ExceptT m) f = ExceptT $ catch m (runExceptT . f)--- | @since 0.9.0-instance MonadMask m => MonadMask (ExceptT e m) where-  mask f = ExceptT $ mask $ \u -> runExceptT $ f (q u)-    where-      q :: (m (Either e a) -> m (Either e a))-        -> ExceptT e m a -> ExceptT e m a-      q u (ExceptT b) = ExceptT (u b)-  uninterruptibleMask f = ExceptT $ uninterruptibleMask $ \u -> runExceptT $ f (q u)-    where-      q :: (m (Either e a) -> m (Either e a))-        -> ExceptT e m a -> ExceptT e m a-      q u (ExceptT b) = ExceptT (u b)--  generalBracket acquire release use = ExceptT $ do-    -- This implementation is given as an example in the documentation of-    -- 'generalBracket', so when changing it, remember to update the-    -- documentation's copy as well-    (eb, ec) <- generalBracket-      (runExceptT acquire)-      (\eresource exitCase -> case eresource of-        Left e -> return (Left e) -- nothing to release, acquire didn't succeed-        Right resource -> case exitCase of-          ExitCaseSuccess (Right b) -> runExceptT (release resource (ExitCaseSuccess b))-          ExitCaseException e       -> runExceptT (release resource (ExitCaseException e))-          _                         -> runExceptT (release resource ExitCaseAbort))-      (either (return . Left) (runExceptT . use))-    return $ do-      -- The order in which we perform those two 'Either' effects determines-      -- which error will win if they are both 'Left's. We want the error from-      -- 'release' to win.-      c <- ec-      b <- eb-      return (b, c)--instance MonadThrow m => MonadThrow (ContT r m) where-  throwM = lift . throwM--- I don't believe any valid of MonadCatch exists for ContT.--- instance MonadCatch m => MonadCatch (ContT r m) where--#if !(MIN_VERSION_transformers(0,6,0))--- | Throws exceptions into the base monad.-instance (Error e, MonadThrow m) => MonadThrow (ErrorT e m) where-  throwM = lift . throwM--- | Catches exceptions from the base monad.-instance (Error e, MonadCatch m) => MonadCatch (ErrorT e m) where-  catch (ErrorT m) f = ErrorT $ catch m (runErrorT . f)-instance (Error e, MonadMask m) => MonadMask (ErrorT e m) where-  mask f = ErrorT $ mask $ \u -> runErrorT $ f (q u)-    where-      q :: (m (Either e a) -> m (Either e a))-        -> ErrorT e m a -> ErrorT e m a-      q u (ErrorT b) = ErrorT (u b)-  uninterruptibleMask f = ErrorT $ uninterruptibleMask $ \u -> runErrorT $ f (q u)-    where-      q :: (m (Either e a) -> m (Either e a))-        -> ErrorT e m a -> ErrorT e m a-      q u (ErrorT b) = ErrorT (u b)--  generalBracket acquire release use = ErrorT $ do-    (eb, ec) <- generalBracket-      (runErrorT acquire)-      (\eresource exitCase -> case eresource of-        Left e -> return (Left e) -- nothing to release, acquire didn't succeed-        Right resource -> case exitCase of-          ExitCaseSuccess (Right b) -> runErrorT (release resource (ExitCaseSuccess b))-          ExitCaseException e       -> runErrorT (release resource (ExitCaseException e))-          _                         -> runErrorT (release resource ExitCaseAbort))-      (either (return . Left) (runErrorT . use))-    return $ do-      -- The order in which we perform those two 'Either' effects determines-      -- which error will win if they are both 'Left's. We want the error from-      -- 'release' to win.-      c <- ec-      b <- eb-      return (b, c)---- Transformers which are only instances of MonadThrow and MonadCatch, not MonadMask-instance MonadThrow m => MonadThrow (ListT m) where-  throwM = lift . throwM-instance MonadCatch m => MonadCatch (ListT m) where-  catch (ListT m) f = ListT $ catch m (runListT . f)-#endif----------------------------------------------------------------------------------- $utilities--- These functions follow those from "Control.Exception", except that they are--- based on methods from the 'MonadCatch' typeclass. See--- "Control.Exception" for API usage.----------------------------------------------------------------------------------- | Like 'mask', but does not pass a @restore@ action to the argument.-mask_ :: MonadMask m => m a -> m a-mask_ io = mask $ \_ -> io---- | Like 'uninterruptibleMask', but does not pass a @restore@ action to the--- argument.-uninterruptibleMask_ :: MonadMask m => m a -> m a-uninterruptibleMask_ io = uninterruptibleMask $ \_ -> io---- | Catches all exceptions, and somewhat defeats the purpose of the extensible--- exception system. Use sparingly.------ /NOTE/ This catches all /exceptions/, but if the monad supports other ways of--- aborting the computation, those other kinds of errors will not be caught.-catchAll :: MonadCatch m => m a -> (SomeException -> m a) -> m a-catchAll = catch---- | Catch all 'IOError' (eqv. 'IOException') exceptions. Still somewhat too--- general, but better than using 'catchAll'. See 'catchIf' for an easy way--- of catching specific 'IOError's based on the predicates in "System.IO.Error".-catchIOError :: MonadCatch m => m a -> (IOError -> m a) -> m a-catchIOError = catch---- | Catch exceptions only if they pass some predicate. Often useful with the--- predicates for testing 'IOError' values in "System.IO.Error".-catchIf :: (MonadCatch m, Exception e) =>-    (e -> Bool) -> m a -> (e -> m a) -> m a-catchIf f a b = a `catch` \e -> if f e then b e else throwM e---- | A more generalized way of determining which exceptions to catch at--- run time.-catchJust :: (MonadCatch m, Exception e) =>-    (e -> Maybe b) -> m a -> (b -> m a) -> m a-catchJust f a b = a `catch` \e -> maybe (throwM e) b $ f e---- | Flipped 'catch'. See "Control.Exception"'s 'ControlException.handle'.-handle :: (MonadCatch m, Exception e) => (e -> m a) -> m a -> m a-handle = flip catch-{-# INLINE handle #-}---- | Flipped 'catchIOError'-handleIOError :: MonadCatch m => (IOError -> m a) -> m a -> m a-handleIOError = handle---- | Flipped 'catchAll'-handleAll :: MonadCatch m => (SomeException -> m a) -> m a -> m a-handleAll = handle---- | Flipped 'catchIf'-handleIf :: (MonadCatch m, Exception e) => (e -> Bool) -> (e -> m a) -> m a -> m a-handleIf f = flip (catchIf f)---- | Flipped 'catchJust'. See "Control.Exception"'s 'ControlException.handleJust'.-handleJust :: (MonadCatch m, Exception e) => (e -> Maybe b) -> (b -> m a) -> m a -> m a-handleJust f = flip (catchJust f)-{-# INLINE handleJust #-}---- | Similar to 'catch', but returns an 'Either' result. See "Control.Exception"'s--- 'Control.Exception.try'.-try :: (MonadCatch m, Exception e) => m a -> m (Either e a)-try a = catch (Right `liftM` a) (return . Left)---- | A variant of 'try' that takes an exception predicate to select--- which exceptions are caught. See "Control.Exception"'s 'ControlException.tryJust'-tryJust :: (MonadCatch m, Exception e) =>-    (e -> Maybe b) -> m a -> m (Either b a)-tryJust f a = catch (Right `liftM` a) (\e -> maybe (throwM e) (return . Left) (f e))---- | Generalized version of 'ControlException.Handler'-data Handler m a = forall e . ControlException.Exception e => Handler (e -> m a)--instance Monad m => Functor (Handler m) where-  fmap f (Handler h) = Handler (liftM f . h)---- | Catches different sorts of exceptions. See "Control.Exception"'s 'ControlException.catches'-catches :: (Foldable f, MonadCatch m) => m a -> f (Handler m a) -> m a-catches a hs = a `catch` handler-  where-    handler e = foldr probe (throwM e) hs-      where-        probe (Handler h) xs = maybe xs h (ControlException.fromException e)---- | Run an action only if an exception is thrown in the main action. The--- exception is not caught, simply rethrown.------ /NOTE/ The action is only run if an /exception/ is thrown. If the monad--- supports other ways of aborting the computation, the action won't run if--- those other kinds of errors are thrown. See 'onError'.-onException :: MonadCatch m => m a -> m b -> m a-onException action handler = action `catchAll` \e -> handler >> throwM e---- | Run an action only if an error is thrown in the main action. Unlike--- 'onException', this works with every kind of error, not just exceptions. For--- example, if @f@ is an 'ExceptT' computation which aborts with a 'Left', the--- computation @onError f g@ will execute @g@, while @onException f g@ will not.------ This distinction is only meaningful for monads which have multiple exit--- points, such as 'Except' and 'MaybeT'. For monads that only have a single--- exit point, there is no difference between 'onException' and 'onError',--- except that 'onError' has a more constrained type.------ @since 0.10.0-onError :: MonadMask m => m a -> m b -> m a-onError action handler = bracketOnError (return ()) (const handler) (const action)---- | Generalized abstracted pattern of safe resource acquisition and release--- in the face of errors. The first action \"acquires\" some value, which--- is \"released\" by the second action at the end. The third action \"uses\"--- the value and its result is the result of the 'bracket'.------ If an error is thrown during the use, the release still happens before the--- error is rethrown.------ Note that this is essentially a type-specialized version of--- 'generalBracket'. This function has a more common signature (matching the--- signature from "Control.Exception"), and is often more convenient to use. By--- contrast, 'generalBracket' is more expressive, allowing us to implement--- other functions like 'bracketOnError'.-bracket :: MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b-bracket acquire release = liftM fst . generalBracket-  acquire-  (\a _exitCase -> release a)---- | Version of 'bracket' without any value being passed to the second and--- third actions.-bracket_ :: MonadMask m => m a -> m c -> m b -> m b-bracket_ before after action = bracket before (const after) (const action)---- | Perform an action with a finalizer action that is run, even if an--- error occurs.-finally :: MonadMask m => m a -> m b -> m a-finally action finalizer = bracket_ (return ()) finalizer action---- | Like 'bracket', but only performs the final action if an error is--- thrown by the in-between computation.-bracketOnError :: MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b-bracketOnError acquire release = liftM fst . generalBracket-  acquire-  (\a exitCase -> case exitCase of-    ExitCaseSuccess _ -> return ()-    _ -> do-      _ <- release a-      return ())+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+
+#ifndef MIN_VERSION_transformers
+#define MIN_VERSION_transformers(x,y,z) 1
+#endif
+
+#if !(MIN_VERSION_transformers(0,6,0))
+{-# OPTIONS_GHC -fno-warn-deprecations #-}
+#endif
+--------------------------------------------------------------------
+-- |
+-- Copyright   :  (C) Edward Kmett 2013-2015, (c) Google Inc. 2012
+-- License     :  BSD-style (see the file LICENSE)
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- This module supports monads that can throw extensible exceptions. The
+-- exceptions are the very same from "Control.Exception", and the operations
+-- offered very similar, but here they are not limited to 'IO'.
+--
+-- This code is in the style of both transformers and mtl, and is compatible
+-- with them, though doesn't mimic the module structure or offer the complete
+-- range of features in those packages.
+--
+-- This is very similar to 'ErrorT' and 'MonadError', but based on features of
+-- "Control.Exception". In particular, it handles the complex case of
+-- asynchronous exceptions by including 'mask' in the typeclass. Note that the
+-- extensible exceptions feature relies on the RankNTypes language extension.
+--------------------------------------------------------------------
+
+module Control.Monad.Catch (
+    -- * Typeclass
+    -- $mtl
+    MonadThrow(..)
+  , MonadCatch(..)
+  , MonadMask(..)
+  , ExitCase(..)
+
+    -- * Utilities
+    -- $utilities
+  , mask_
+  , uninterruptibleMask_
+  , catchAll
+  , catchIOError
+  , catchJust
+  , catchIf
+  , Handler(..), catches
+  , handle
+  , handleAll
+  , handleIOError
+  , handleJust
+  , handleIf
+  , try
+  , tryJust
+  , onException
+  , onError
+  , bracket
+  , bracket_
+  , finally
+  , bracketOnError
+    -- * Re-exports from Control.Exception
+  , Exception(..)
+  , SomeException(..)
+  ) where
+
+import Control.Exception (Exception(..), SomeException(..))
+import qualified Control.Exception as ControlException
+import Control.Monad (liftM)
+import qualified Control.Monad.STM as STM
+import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS
+import qualified Control.Monad.Trans.RWS.Strict as StrictRWS
+import qualified Control.Monad.Trans.State.Lazy as LazyS
+import qualified Control.Monad.Trans.State.Strict as StrictS
+import qualified Control.Monad.Trans.Writer.Lazy as LazyW
+import qualified Control.Monad.Trans.Writer.Strict as StrictW
+import Control.Monad.ST (ST)
+import Control.Monad.STM (STM)
+import Control.Monad.Trans.Class (MonadTrans(..))
+import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
+import Control.Monad.Trans.Except (ExceptT(..), runExceptT)
+import Control.Monad.Trans.Cont (ContT)
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Reader (ReaderT(..), runReaderT)
+
+import Language.Haskell.TH.Syntax (Q)
+
+#if MIN_VERSION_base(4,4,0)
+import Control.Monad.ST.Unsafe (unsafeIOToST)
+#else
+import Control.Monad.ST (unsafeIOToST)
+#endif
+
+#if __GLASGOW_HASKELL__ < 706
+import Prelude hiding (catch, foldr)
+import Data.Foldable
+import Data.Monoid
+#elif __GLASGOW_HASKELL__ < 710
+import Prelude hiding (foldr)
+import Data.Foldable
+import Data.Monoid
+#endif
+
+#if __GLASGOW_HASKELL__ < 710
+import Control.Applicative
+#endif
+
+#if __GLASGOW_HASKELL__ >= 800
+import GHC.Stack (HasCallStack, withFrozenCallStack)
+#else
+import Data.CallStack (HasCallStack)
+#endif
+
+#if !(MIN_VERSION_transformers(0,6,0))
+import Control.Monad.Trans.Error (ErrorT(..), Error, runErrorT)
+import Control.Monad.Trans.List (ListT(..), runListT)
+#endif
+
+#if __GLASGOW_HASKELL__ < 800
+withFrozenCallStack :: a -> a
+withFrozenCallStack a = a
+#endif
+
+------------------------------------------------------------------------------
+-- $mtl
+-- The mtl style typeclass
+------------------------------------------------------------------------------
+
+-- | A class for monads in which exceptions may be thrown.
+--
+-- Instances should obey the following law:
+--
+-- > throwM e >> x = throwM e
+--
+-- In other words, throwing an exception short-circuits the rest of the monadic
+-- computation.
+class Monad m => MonadThrow m where
+  -- | Throw an exception. Note that this throws when this action is run in
+  -- the monad @m@, not when it is applied. It is a generalization of
+  -- "Control.Exception"'s 'ControlException.throwIO'.
+  --
+  -- Should satisfy the law:
+  --
+  -- > throwM e >> f = throwM e
+  throwM :: (HasCallStack, Exception e) => e -> m a
+
+-- | A class for monads which allow exceptions to be caught, in particular
+-- exceptions which were thrown by 'throwM'.
+--
+-- Instances should obey the following law:
+--
+-- > catch (throwM e) f = f e
+--
+-- Note that the ability to catch an exception does /not/ guarantee that we can
+-- deal with all possible exit points from a computation. Some monads, such as
+-- continuation-based stacks, allow for more than just a success/failure
+-- strategy, and therefore @catch@ /cannot/ be used by those monads to properly
+-- implement a function such as @finally@. For more information, see
+-- 'MonadMask'.
+class MonadThrow m => MonadCatch m where
+  -- | Provide a handler for exceptions thrown during execution of the first
+  -- action. Note that type of the type of the argument to the handler will
+  -- constrain which exceptions are caught. See "Control.Exception"'s
+  -- 'ControlException.catch'.
+  catch :: (HasCallStack, Exception e) => m a -> (e -> m a) -> m a
+
+-- | A class for monads which provide for the ability to account for
+-- all possible exit points from a computation, and to mask
+-- asynchronous exceptions. Continuation-based monads are invalid
+-- instances of this class.
+--
+-- Instances should ensure that, in the following code:
+--
+-- > fg = f `finally` g
+--
+-- The action @g@ is called regardless of what occurs within @f@, including
+-- async exceptions. Some monads allow @f@ to abort the computation via other
+-- effects than throwing an exception. For simplicity, we will consider aborting
+-- and throwing an exception to be two forms of "throwing an error".
+--
+-- If @f@ and @g@ both throw an error, the error thrown by @fg@ depends on which
+-- errors we're talking about. In a monad transformer stack, the deeper layers
+-- override the effects of the inner layers; for example, @ExceptT e1 (Except
+-- e2) a@ represents a value of type @Either e2 (Either e1 a)@, so throwing both
+-- an @e1@ and an @e2@ will result in @Left e2@. If @f@ and @g@ both throw an
+-- error from the same layer, instances should ensure that the error from @g@
+-- wins.
+--
+-- Effects other than throwing an error are also overridden by the deeper layers.
+-- For example, @StateT s Maybe a@ represents a value of type @s -> Maybe (a,
+-- s)@, so if an error thrown from @f@ causes this function to return @Nothing@,
+-- any changes to the state which @f@ also performed will be erased. As a
+-- result, @g@ will see the state as it was before @f@. Once @g@ completes,
+-- @f@'s error will be rethrown, so @g@' state changes will be erased as well.
+-- This is the normal interaction between effects in a monad transformer stack.
+--
+-- By contrast, <https://hackage.haskell.org/package/lifted-base lifted-base>'s
+-- version of 'finally' always discards all of @g@'s non-IO effects, and @g@
+-- never sees any of @f@'s non-IO effects, regardless of the layer ordering and
+-- regardless of whether @f@ throws an error. This is not the result of
+-- interacting effects, but a consequence of @MonadBaseControl@'s approach.
+class MonadCatch m => MonadMask m where
+  -- | Runs an action with asynchronous exceptions disabled. The action is
+  -- provided a method for restoring the async. environment to what it was
+  -- at the 'mask' call. See "Control.Exception"'s 'ControlException.mask'.
+  mask :: HasCallStack => ((forall a. m a -> m a) -> m b) -> m b
+
+  -- | Like 'mask', but the masked computation is not interruptible (see
+  -- "Control.Exception"'s 'ControlException.uninterruptibleMask'. WARNING:
+  -- Only use if you need to mask exceptions around an interruptible operation
+  -- AND you can guarantee the interruptible operation will only block for a
+  -- short period of time. Otherwise you render the program/thread unresponsive
+  -- and/or unkillable.
+  uninterruptibleMask :: HasCallStack => ((forall a. m a -> m a) -> m b) -> m b
+
+  -- | A generalized version of 'bracket' which uses 'ExitCase' to distinguish
+  -- the different exit cases, and returns the values of both the 'use' and
+  -- 'release' actions. In practice, this extra information is rarely needed,
+  -- so it is often more convenient to use one of the simpler functions which
+  -- are defined in terms of this one, such as 'bracket', 'finally', 'onError',
+  -- and 'bracketOnError'.
+  --
+  -- This function exists because in order to thread their effects through the
+  -- execution of 'bracket', monad transformers need values to be threaded from
+  -- 'use' to 'release' and from 'release' to the output value.
+  --
+  -- /NOTE/ This method was added in version 0.9.0 of this
+  -- library. Previously, implementation of functions like 'bracket'
+  -- and 'finally' in this module were based on the 'mask' and
+  -- 'uninterruptibleMask' functions only, disallowing some classes of
+  -- tranformers from having @MonadMask@ instances (notably
+  -- multi-exit-point transformers like 'ExceptT'). If you are a
+  -- library author, you'll now need to provide an implementation for
+  -- this method. The @StateT@ implementation demonstrates most of the
+  -- subtleties:
+  --
+  -- @
+  -- generalBracket acquire release use = StateT $ \s0 -> do
+  --   ((b, _s2), (c, s3)) <- generalBracket
+  --     (runStateT acquire s0)
+  --     (\(resource, s1) exitCase -> case exitCase of
+  --       ExitCaseSuccess (b, s2) -> runStateT (release resource (ExitCaseSuccess b)) s2
+  --
+  --       -- In the two other cases, the base monad overrides @use@'s state
+  --       -- changes and the state reverts to @s1@.
+  --       ExitCaseException e     -> runStateT (release resource (ExitCaseException e)) s1
+  --       ExitCaseAbort           -> runStateT (release resource ExitCaseAbort) s1
+  --     )
+  --     (\(resource, s1) -> runStateT (use resource) s1)
+  --   return ((b, c), s3)
+  -- @
+  --
+  -- The @StateT s m@ implementation of @generalBracket@ delegates to the @m@
+  -- implementation of @generalBracket@. The @acquire@, @use@, and @release@
+  -- arguments given to @StateT@'s implementation produce actions of type
+  -- @StateT s m a@, @StateT s m b@, and @StateT s m c@. In order to run those
+  -- actions in the base monad, we need to call @runStateT@, from which we
+  -- obtain actions of type @m (a, s)@, @m (b, s)@, and @m (c, s)@. Since each
+  -- action produces the next state, it is important to feed the state produced
+  -- by the previous action to the next action.
+  --
+  -- In the 'ExitCaseSuccess' case, the state starts at @s0@, flows through
+  -- @acquire@ to become @s1@, flows through @use@ to become @s2@, and finally
+  -- flows through @release@ to become @s3@. In the other two cases, @release@
+  -- does not receive the value @s2@, so its action cannot see the state changes
+  -- performed by @use@. This is fine, because in those two cases, an error was
+  -- thrown in the base monad, so as per the usual interaction between effects
+  -- in a monad transformer stack, those state changes get reverted. So we start
+  -- from @s1@ instead.
+  --
+  -- Finally, the @m@ implementation of @generalBracket@ returns the pairs
+  -- @(b, s)@ and @(c, s)@. For monad transformers other than @StateT@, this
+  -- will be some other type representing the effects and values performed and
+  -- returned by the @use@ and @release@ actions. The effect part of the @use@
+  -- result, in this case @_s2@, usually needs to be discarded, since those
+  -- effects have already been incorporated in the @release@ action.
+  --
+  -- The only effect which is intentionally not incorporated in the @release@
+  -- action is the effect of throwing an error. In that case, the error must be
+  -- re-thrown. One subtlety which is easy to miss is that in the case in which
+  -- @use@ and @release@ both throw an error, the error from @release@ should
+  -- take priority. Here is an implementation for @ExceptT@ which demonstrates
+  -- how to do this.
+  --
+  -- @
+  -- generalBracket acquire release use = ExceptT $ do
+  --   (eb, ec) <- generalBracket
+  --     (runExceptT acquire)
+  --     (\eresource exitCase -> case eresource of
+  --       Left e -> return (Left e) -- nothing to release, acquire didn't succeed
+  --       Right resource -> case exitCase of
+  --         ExitCaseSuccess (Right b) -> runExceptT (release resource (ExitCaseSuccess b))
+  --         ExitCaseException e       -> runExceptT (release resource (ExitCaseException e))
+  --         _                         -> runExceptT (release resource ExitCaseAbort))
+  --     (either (return . Left) (runExceptT . use))
+  --   return $ do
+  --     -- The order in which we perform those two 'Either' effects determines
+  --     -- which error will win if they are both 'Left's. We want the error from
+  --     -- 'release' to win.
+  --     c <- ec
+  --     b <- eb
+  --     return (b, c)
+  -- @
+  --
+  -- @since 0.9.0
+  generalBracket
+    :: HasCallStack
+    => m a
+    -- ^ acquire some resource
+    -> (a -> ExitCase b -> m c)
+    -- ^ release the resource, observing the outcome of the inner action
+    -> (a -> m b)
+    -- ^ inner action to perform with the resource
+    -> m (b, c)
+
+-- | A 'MonadMask' computation may either succeed with a value, abort with an
+-- exception, or abort for some other reason. For example, in @ExceptT e IO@
+-- you can use 'throwM' to abort with an exception ('ExitCaseException') or
+-- 'Control.Monad.Trans.Except.throwE' to abort with a value of type 'e'
+-- ('ExitCaseAbort').
+data ExitCase a
+  = ExitCaseSuccess a
+  | ExitCaseException SomeException
+  | ExitCaseAbort
+  deriving Show
+
+instance MonadThrow [] where
+  throwM _ = []
+instance MonadThrow Maybe where
+  throwM _ = Nothing
+instance MonadThrow Q where
+  throwM = fail . show
+
+instance MonadThrow IO where
+  throwM = ControlException.throwIO
+instance MonadCatch IO where
+  catch = ControlException.catch
+instance MonadMask IO where
+  mask = ControlException.mask
+  uninterruptibleMask = ControlException.uninterruptibleMask
+  generalBracket acquire release use = mask $ \unmasked -> do
+    resource <- acquire
+    b <- unmasked (use resource) `catch` \e -> do
+      _ <- release resource (ExitCaseException e)
+      throwM e
+    c <- release resource (ExitCaseSuccess b)
+    return (b, c)
+
+instance MonadThrow (ST s) where
+  throwM = unsafeIOToST . ControlException.throwIO
+
+instance MonadThrow STM where
+  throwM = STM.throwSTM
+instance MonadCatch STM where
+  catch = STM.catchSTM
+
+instance e ~ SomeException => MonadThrow (Either e) where
+  throwM = Left . toException
+-- | @since 0.8.3
+instance e ~ SomeException => MonadCatch (Either e) where
+  catch (Left e) f =
+    case fromException e of
+      Nothing -> Left e
+      Just e' -> f e'
+  catch x@(Right _) _ = x
+-- | @since 0.8.3
+instance e ~ SomeException => MonadMask (Either e) where
+  mask f = f id
+  uninterruptibleMask f = f id
+
+  generalBracket acquire release use =
+    case acquire of
+      Left e -> Left e
+      Right resource ->
+        case use resource of
+          Left e -> release resource (ExitCaseException e) >> Left e
+          Right b -> do
+            c <- release resource (ExitCaseSuccess b)
+            return (b, c)
+
+instance MonadThrow m => MonadThrow (IdentityT m) where
+  throwM e = lift $ throwM e
+instance MonadCatch m => MonadCatch (IdentityT m) where
+  catch (IdentityT m) f = IdentityT (catch m (runIdentityT . f))
+instance MonadMask m => MonadMask (IdentityT m) where
+  mask a = IdentityT $ mask $ \u -> runIdentityT (a $ q u)
+    where q :: (m a -> m a) -> IdentityT m a -> IdentityT m a
+          q u = IdentityT . u . runIdentityT
+  uninterruptibleMask a =
+    IdentityT $ uninterruptibleMask $ \u -> runIdentityT (a $ q u)
+      where q :: (m a -> m a) -> IdentityT m a -> IdentityT m a
+            q u = IdentityT . u . runIdentityT
+
+  generalBracket acquire release use = IdentityT $
+    generalBracket
+      (runIdentityT acquire)
+      (\resource exitCase -> runIdentityT (release resource exitCase))
+      (\resource -> runIdentityT (use resource))
+
+instance MonadThrow m => MonadThrow (LazyS.StateT s m) where
+  throwM e = lift $ throwM e
+instance MonadCatch m => MonadCatch (LazyS.StateT s m) where
+  catch = LazyS.liftCatch catch
+instance MonadMask m => MonadMask (LazyS.StateT s m) where
+  mask a = LazyS.StateT $ \s -> mask $ \u -> LazyS.runStateT (a $ q u) s
+    where q :: (m (a, s) -> m (a, s)) -> LazyS.StateT s m a -> LazyS.StateT s m a
+          q u (LazyS.StateT b) = LazyS.StateT (u . b)
+  uninterruptibleMask a =
+    LazyS.StateT $ \s -> uninterruptibleMask $ \u -> LazyS.runStateT (a $ q u) s
+      where q :: (m (a, s) -> m (a, s)) -> LazyS.StateT s m a -> LazyS.StateT s m a
+            q u (LazyS.StateT b) = LazyS.StateT (u . b)
+
+  generalBracket acquire release use = LazyS.StateT $ \s0 -> do
+    -- This implementation is given as an example in the documentation of
+    -- 'generalBracket', so when changing it, remember to update the
+    -- documentation's copy as well
+    ((b, _s2), (c, s3)) <- generalBracket
+      (LazyS.runStateT acquire s0)
+      (\(resource, s1) exitCase -> case exitCase of
+        ExitCaseSuccess (b, s2) -> LazyS.runStateT (release resource (ExitCaseSuccess b)) s2
+        -- In the two other cases, the base monad overrides @use@'s state
+        -- changes and the state reverts to @s1@.
+        ExitCaseException e     -> LazyS.runStateT (release resource (ExitCaseException e)) s1
+        ExitCaseAbort           -> LazyS.runStateT (release resource ExitCaseAbort) s1)
+      (\(resource, s1) -> LazyS.runStateT (use resource) s1)
+    return ((b, c), s3)
+
+instance MonadThrow m => MonadThrow (StrictS.StateT s m) where
+  throwM e = lift $ throwM e
+instance MonadCatch m => MonadCatch (StrictS.StateT s m) where
+  catch = StrictS.liftCatch catch
+instance MonadMask m => MonadMask (StrictS.StateT s m) where
+  mask a = StrictS.StateT $ \s -> mask $ \u -> StrictS.runStateT (a $ q u) s
+    where q :: (m (a, s) -> m (a, s)) -> StrictS.StateT s m a -> StrictS.StateT s m a
+          q u (StrictS.StateT b) = StrictS.StateT (u . b)
+  uninterruptibleMask a =
+    StrictS.StateT $ \s -> uninterruptibleMask $ \u -> StrictS.runStateT (a $ q u) s
+      where q :: (m (a, s) -> m (a, s)) -> StrictS.StateT s m a -> StrictS.StateT s m a
+            q u (StrictS.StateT b) = StrictS.StateT (u . b)
+
+  generalBracket acquire release use = StrictS.StateT $ \s0 -> do
+    ((b, _s2), (c, s3)) <- generalBracket
+      (StrictS.runStateT acquire s0)
+      (\(resource, s1) exitCase -> case exitCase of
+        ExitCaseSuccess (b, s2) -> StrictS.runStateT (release resource (ExitCaseSuccess b)) s2
+        -- In the two other cases, the base monad overrides @use@'s state
+        -- changes and the state reverts to @s1@.
+        ExitCaseException e     -> StrictS.runStateT (release resource (ExitCaseException e)) s1
+        ExitCaseAbort           -> StrictS.runStateT (release resource ExitCaseAbort) s1)
+      (\(resource, s1) -> StrictS.runStateT (use resource) s1)
+    return ((b, c), s3)
+
+instance MonadThrow m => MonadThrow (ReaderT r m) where
+  throwM e = lift $ throwM e
+instance MonadCatch m => MonadCatch (ReaderT r m) where
+  catch (ReaderT m) c = ReaderT $ \r -> m r `catch` \e -> runReaderT (c e) r
+instance MonadMask m => MonadMask (ReaderT r m) where
+  mask a = ReaderT $ \e -> mask $ \u -> runReaderT (a $ q u) e
+    where q :: (m a -> m a) -> ReaderT e m a -> ReaderT e m a
+          q u (ReaderT b) = ReaderT (u . b)
+  uninterruptibleMask a =
+    ReaderT $ \e -> uninterruptibleMask $ \u -> runReaderT (a $ q u) e
+      where q :: (m a -> m a) -> ReaderT e m a -> ReaderT e m a
+            q u (ReaderT b) = ReaderT (u . b)
+
+  generalBracket acquire release use = ReaderT $ \r ->
+    generalBracket
+      (runReaderT acquire r)
+      (\resource exitCase -> runReaderT (release resource exitCase) r)
+      (\resource -> runReaderT (use resource) r)
+
+instance (MonadThrow m, Monoid w) => MonadThrow (StrictW.WriterT w m) where
+  throwM e = lift $ throwM e
+instance (MonadCatch m, Monoid w) => MonadCatch (StrictW.WriterT w m) where
+  catch (StrictW.WriterT m) h = StrictW.WriterT $ m `catch ` \e -> StrictW.runWriterT (h e)
+instance (MonadMask m, Monoid w) => MonadMask (StrictW.WriterT w m) where
+  mask a = StrictW.WriterT $ mask $ \u -> StrictW.runWriterT (a $ q u)
+    where q :: (m (a, w) -> m (a, w)) -> StrictW.WriterT w m a -> StrictW.WriterT w m a
+          q u b = StrictW.WriterT $ u (StrictW.runWriterT b)
+  uninterruptibleMask a =
+    StrictW.WriterT $ uninterruptibleMask $ \u -> StrictW.runWriterT (a $ q u)
+      where q :: (m (a, w) -> m (a, w)) -> StrictW.WriterT w m a -> StrictW.WriterT w m a
+            q u b = StrictW.WriterT $ u (StrictW.runWriterT b)
+
+  generalBracket acquire release use = StrictW.WriterT $ do
+    ((b, _w12), (c, w123)) <- generalBracket
+      (StrictW.runWriterT acquire)
+      (\(resource, w1) exitCase -> case exitCase of
+        ExitCaseSuccess (b, w12) -> do
+          (c, w3) <- StrictW.runWriterT (release resource (ExitCaseSuccess b))
+          return (c, mappend w12 w3)
+        -- In the two other cases, the base monad overrides @use@'s state
+        -- changes and the state reverts to @w1@.
+        ExitCaseException e -> do
+          (c, w3) <- StrictW.runWriterT (release resource (ExitCaseException e))
+          return (c, mappend w1 w3)
+        ExitCaseAbort -> do
+          (c, w3) <- StrictW.runWriterT (release resource ExitCaseAbort)
+          return (c, mappend w1 w3))
+      (\(resource, w1) -> do
+        (a, w2) <- StrictW.runWriterT (use resource)
+        return (a, mappend w1 w2))
+    return ((b, c), w123)
+
+instance (MonadThrow m, Monoid w) => MonadThrow (LazyW.WriterT w m) where
+  throwM e = lift $ throwM e
+instance (MonadCatch m, Monoid w) => MonadCatch (LazyW.WriterT w m) where
+  catch (LazyW.WriterT m) h = LazyW.WriterT $ m `catch ` \e -> LazyW.runWriterT (h e)
+instance (MonadMask m, Monoid w) => MonadMask (LazyW.WriterT w m) where
+  mask a = LazyW.WriterT $ mask $ \u -> LazyW.runWriterT (a $ q u)
+    where q :: (m (a, w) -> m (a, w)) -> LazyW.WriterT w m a -> LazyW.WriterT w m a
+          q u b = LazyW.WriterT $ u (LazyW.runWriterT b)
+  uninterruptibleMask a =
+    LazyW.WriterT $ uninterruptibleMask $ \u -> LazyW.runWriterT (a $ q u)
+      where q :: (m (a, w) -> m (a, w)) -> LazyW.WriterT w m a -> LazyW.WriterT w m a
+            q u b = LazyW.WriterT $ u (LazyW.runWriterT b)
+
+  generalBracket acquire release use = LazyW.WriterT $ do
+    ((b, _w12), (c, w123)) <- generalBracket
+      (LazyW.runWriterT acquire)
+      (\(resource, w1) exitCase -> case exitCase of
+        ExitCaseSuccess (b, w12) -> do
+          (c, w3) <- LazyW.runWriterT (release resource (ExitCaseSuccess b))
+          return (c, mappend w12 w3)
+        -- In the two other cases, the base monad overrides @use@'s state
+        -- changes and the state reverts to @w1@.
+        ExitCaseException e -> do
+          (c, w3) <- LazyW.runWriterT (release resource (ExitCaseException e))
+          return (c, mappend w1 w3)
+        ExitCaseAbort -> do
+          (c, w3) <- LazyW.runWriterT (release resource ExitCaseAbort)
+          return (c, mappend w1 w3))
+      (\(resource, w1) -> do
+        (a, w2) <- LazyW.runWriterT (use resource)
+        return (a, mappend w1 w2))
+    return ((b, c), w123)
+
+instance (MonadThrow m, Monoid w) => MonadThrow (LazyRWS.RWST r w s m) where
+  throwM e = lift $ throwM e
+instance (MonadCatch m, Monoid w) => MonadCatch (LazyRWS.RWST r w s m) where
+  catch (LazyRWS.RWST m) h = LazyRWS.RWST $ \r s -> m r s `catch` \e -> LazyRWS.runRWST (h e) r s
+instance (MonadMask m, Monoid w) => MonadMask (LazyRWS.RWST r w s m) where
+  mask a = LazyRWS.RWST $ \r s -> mask $ \u -> LazyRWS.runRWST (a $ q u) r s
+    where q :: (m (a, s, w) -> m (a, s, w)) -> LazyRWS.RWST r w s m a -> LazyRWS.RWST r w s m a
+          q u (LazyRWS.RWST b) = LazyRWS.RWST $ \ r s -> u (b r s)
+  uninterruptibleMask a =
+    LazyRWS.RWST $ \r s -> uninterruptibleMask $ \u -> LazyRWS.runRWST (a $ q u) r s
+      where q :: (m (a, s, w) -> m (a, s, w)) -> LazyRWS.RWST r w s m a -> LazyRWS.RWST r w s m a
+            q u (LazyRWS.RWST b) = LazyRWS.RWST $ \ r s -> u (b r s)
+
+  generalBracket acquire release use = LazyRWS.RWST $ \r s0 -> do
+    ((b, _s2, _w12), (c, s3, w123)) <- generalBracket
+      (LazyRWS.runRWST acquire r s0)
+      (\(resource, s1, w1) exitCase -> case exitCase of
+        ExitCaseSuccess (b, s2, w12) -> do
+          (c, s3, w3) <- LazyRWS.runRWST (release resource (ExitCaseSuccess b)) r s2
+          return (c, s3, mappend w12 w3)
+        -- In the two other cases, the base monad overrides @use@'s state
+        -- changes and the state reverts to @s1@ and @w1@.
+        ExitCaseException e -> do
+          (c, s3, w3) <- LazyRWS.runRWST (release resource (ExitCaseException e)) r s1
+          return (c, s3, mappend w1 w3)
+        ExitCaseAbort -> do
+          (c, s3, w3) <- LazyRWS.runRWST (release resource ExitCaseAbort) r s1
+          return (c, s3, mappend w1 w3))
+      (\(resource, s1, w1) -> do
+        (a, s2, w2) <- LazyRWS.runRWST (use resource) r s1
+        return (a, s2, mappend w1 w2))
+    return ((b, c), s3, w123)
+
+instance (MonadThrow m, Monoid w) => MonadThrow (StrictRWS.RWST r w s m) where
+  throwM e = lift $ throwM e
+instance (MonadCatch m, Monoid w) => MonadCatch (StrictRWS.RWST r w s m) where
+  catch (StrictRWS.RWST m) h = StrictRWS.RWST $ \r s -> m r s `catch` \e -> StrictRWS.runRWST (h e) r s
+instance (MonadMask m, Monoid w) => MonadMask (StrictRWS.RWST r w s m) where
+  mask a = StrictRWS.RWST $ \r s -> mask $ \u -> StrictRWS.runRWST (a $ q u) r s
+    where q :: (m (a, s, w) -> m (a, s, w)) -> StrictRWS.RWST r w s m a -> StrictRWS.RWST r w s m a
+          q u (StrictRWS.RWST b) = StrictRWS.RWST $ \ r s -> u (b r s)
+  uninterruptibleMask a =
+    StrictRWS.RWST $ \r s -> uninterruptibleMask $ \u -> StrictRWS.runRWST (a $ q u) r s
+      where q :: (m (a, s, w) -> m (a, s, w)) -> StrictRWS.RWST r w s m a -> StrictRWS.RWST r w s m a
+            q u (StrictRWS.RWST b) = StrictRWS.RWST $ \ r s -> u (b r s)
+
+  generalBracket acquire release use = StrictRWS.RWST $ \r s0 -> do
+    ((b, _s2, _w12), (c, s3, w123)) <- generalBracket
+      (StrictRWS.runRWST acquire r s0)
+      (\(resource, s1, w1) exitCase -> case exitCase of
+        ExitCaseSuccess (b, s2, w12) -> do
+          (c, s3, w3) <- StrictRWS.runRWST (release resource (ExitCaseSuccess b)) r s2
+          return (c, s3, mappend w12 w3)
+        -- In the two other cases, the base monad overrides @use@'s state
+        -- changes and the state reverts to @s1@ and @w1@.
+        ExitCaseException e -> do
+          (c, s3, w3) <- StrictRWS.runRWST (release resource (ExitCaseException e)) r s1
+          return (c, s3, mappend w1 w3)
+        ExitCaseAbort -> do
+          (c, s3, w3) <- StrictRWS.runRWST (release resource ExitCaseAbort) r s1
+          return (c, s3, mappend w1 w3))
+      (\(resource, s1, w1) -> do
+        (a, s2, w2) <- StrictRWS.runRWST (use resource) r s1
+        return (a, s2, mappend w1 w2))
+    return ((b, c), s3, w123)
+
+-- | Throws exceptions into the base monad.
+instance MonadThrow m => MonadThrow (MaybeT m) where
+  throwM = lift . throwM
+-- | Catches exceptions from the base monad.
+instance MonadCatch m => MonadCatch (MaybeT m) where
+  catch (MaybeT m) f = MaybeT $ catch m (runMaybeT . f)
+-- | @since 0.10.0
+instance MonadMask m => MonadMask (MaybeT m) where
+  mask f = MaybeT $ mask $ \u -> runMaybeT $ f (q u)
+    where
+      q :: (m (Maybe a) -> m (Maybe a))
+        -> MaybeT m a -> MaybeT m a
+      q u (MaybeT b) = MaybeT (u b)
+  uninterruptibleMask f = MaybeT $ uninterruptibleMask $ \u -> runMaybeT $ f (q u)
+    where
+      q :: (m (Maybe a) -> m (Maybe a))
+        -> MaybeT m a -> MaybeT m a
+      q u (MaybeT b) = MaybeT (u b)
+
+  generalBracket acquire release use = MaybeT $ do
+    (eb, ec) <- generalBracket
+      (runMaybeT acquire)
+      (\resourceMay exitCase -> case resourceMay of
+        Nothing -> return Nothing -- nothing to release, acquire didn't succeed
+        Just resource -> case exitCase of
+          ExitCaseSuccess (Just b) -> runMaybeT (release resource (ExitCaseSuccess b))
+          ExitCaseException e      -> runMaybeT (release resource (ExitCaseException e))
+          _                        -> runMaybeT (release resource ExitCaseAbort))
+      (\resourceMay -> case resourceMay of
+        Nothing -> return Nothing
+        Just resource -> runMaybeT (use resource))
+    -- The order in which we perform those two 'Maybe' effects doesn't matter,
+    -- since the error message is the same regardless.
+    return ((,) <$> eb <*> ec)
+
+-- | Throws exceptions into the base monad.
+instance MonadThrow m => MonadThrow (ExceptT e m) where
+  throwM = lift . throwM
+-- | Catches exceptions from the base monad.
+instance MonadCatch m => MonadCatch (ExceptT e m) where
+  catch (ExceptT m) f = ExceptT $ catch m (runExceptT . f)
+-- | @since 0.9.0
+instance MonadMask m => MonadMask (ExceptT e m) where
+  mask f = ExceptT $ mask $ \u -> runExceptT $ f (q u)
+    where
+      q :: (m (Either e a) -> m (Either e a))
+        -> ExceptT e m a -> ExceptT e m a
+      q u (ExceptT b) = ExceptT (u b)
+  uninterruptibleMask f = ExceptT $ uninterruptibleMask $ \u -> runExceptT $ f (q u)
+    where
+      q :: (m (Either e a) -> m (Either e a))
+        -> ExceptT e m a -> ExceptT e m a
+      q u (ExceptT b) = ExceptT (u b)
+
+  generalBracket acquire release use = ExceptT $ do
+    -- This implementation is given as an example in the documentation of
+    -- 'generalBracket', so when changing it, remember to update the
+    -- documentation's copy as well
+    (eb, ec) <- generalBracket
+      (runExceptT acquire)
+      (\eresource exitCase -> case eresource of
+        Left e -> return (Left e) -- nothing to release, acquire didn't succeed
+        Right resource -> case exitCase of
+          ExitCaseSuccess (Right b) -> runExceptT (release resource (ExitCaseSuccess b))
+          ExitCaseException e       -> runExceptT (release resource (ExitCaseException e))
+          _                         -> runExceptT (release resource ExitCaseAbort))
+      (either (return . Left) (runExceptT . use))
+    return $ do
+      -- The order in which we perform those two 'Either' effects determines
+      -- which error will win if they are both 'Left's. We want the error from
+      -- 'release' to win.
+      c <- ec
+      b <- eb
+      return (b, c)
+
+instance MonadThrow m => MonadThrow (ContT r m) where
+  throwM = lift . throwM
+-- I don't believe any valid of MonadCatch exists for ContT.
+-- instance MonadCatch m => MonadCatch (ContT r m) where
+
+#if !(MIN_VERSION_transformers(0,6,0))
+-- | Throws exceptions into the base monad.
+instance (Error e, MonadThrow m) => MonadThrow (ErrorT e m) where
+  throwM = lift . throwM
+-- | Catches exceptions from the base monad.
+instance (Error e, MonadCatch m) => MonadCatch (ErrorT e m) where
+  catch (ErrorT m) f = ErrorT $ catch m (runErrorT . f)
+instance (Error e, MonadMask m) => MonadMask (ErrorT e m) where
+  mask f = ErrorT $ mask $ \u -> runErrorT $ f (q u)
+    where
+      q :: (m (Either e a) -> m (Either e a))
+        -> ErrorT e m a -> ErrorT e m a
+      q u (ErrorT b) = ErrorT (u b)
+  uninterruptibleMask f = ErrorT $ uninterruptibleMask $ \u -> runErrorT $ f (q u)
+    where
+      q :: (m (Either e a) -> m (Either e a))
+        -> ErrorT e m a -> ErrorT e m a
+      q u (ErrorT b) = ErrorT (u b)
+
+  generalBracket acquire release use = ErrorT $ do
+    (eb, ec) <- generalBracket
+      (runErrorT acquire)
+      (\eresource exitCase -> case eresource of
+        Left e -> return (Left e) -- nothing to release, acquire didn't succeed
+        Right resource -> case exitCase of
+          ExitCaseSuccess (Right b) -> runErrorT (release resource (ExitCaseSuccess b))
+          ExitCaseException e       -> runErrorT (release resource (ExitCaseException e))
+          _                         -> runErrorT (release resource ExitCaseAbort))
+      (either (return . Left) (runErrorT . use))
+    return $ do
+      -- The order in which we perform those two 'Either' effects determines
+      -- which error will win if they are both 'Left's. We want the error from
+      -- 'release' to win.
+      c <- ec
+      b <- eb
+      return (b, c)
+
+-- Transformers which are only instances of MonadThrow and MonadCatch, not MonadMask
+instance MonadThrow m => MonadThrow (ListT m) where
+  throwM = lift . throwM
+instance MonadCatch m => MonadCatch (ListT m) where
+  catch (ListT m) f = ListT $ catch m (runListT . f)
+#endif
+
+------------------------------------------------------------------------------
+-- $utilities
+-- These functions follow those from "Control.Exception", except that they are
+-- based on methods from the 'MonadCatch' typeclass. See
+-- "Control.Exception" for API usage.
+------------------------------------------------------------------------------
+
+-- | Like 'mask', but does not pass a @restore@ action to the argument.
+mask_ :: (HasCallStack, MonadMask m) => m a -> m a
+mask_ io = withFrozenCallStack (\f -> mask (\x -> f x)) (\_ -> io)
+
+-- | Like 'uninterruptibleMask', but does not pass a @restore@ action to the
+-- argument.
+uninterruptibleMask_ :: (HasCallStack, MonadMask m) => m a -> m a
+uninterruptibleMask_ io = withFrozenCallStack (\f -> uninterruptibleMask (\x -> f x)) (\_ -> io)
+
+-- | Catches all exceptions, and somewhat defeats the purpose of the extensible
+-- exception system. Use sparingly.
+--
+-- /NOTE/ This catches all /exceptions/, but if the monad supports other ways of
+-- aborting the computation, those other kinds of errors will not be caught.
+catchAll :: (HasCallStack, MonadCatch m) => m a -> (SomeException -> m a) -> m a
+catchAll = withFrozenCallStack catch
+
+-- | Catch all 'IOError' (eqv. 'IOException') exceptions. Still somewhat too
+-- general, but better than using 'catchAll'. See 'catchIf' for an easy way
+-- of catching specific 'IOError's based on the predicates in "System.IO.Error".
+catchIOError :: (HasCallStack, MonadCatch m) => m a -> (IOError -> m a) -> m a
+catchIOError = withFrozenCallStack catch
+
+-- | Catch exceptions only if they pass some predicate. Often useful with the
+-- predicates for testing 'IOError' values in "System.IO.Error".
+catchIf :: (HasCallStack, MonadCatch m, Exception e) =>
+    (e -> Bool) -> m a -> (e -> m a) -> m a
+catchIf f a b = withFrozenCallStack catch a (\e -> if f e then b e else throwM e)
+
+-- | A more generalized way of determining which exceptions to catch at
+-- run time.
+catchJust :: (HasCallStack, MonadCatch m, Exception e) =>
+    (e -> Maybe b) -> m a -> (b -> m a) -> m a
+catchJust f a b = withFrozenCallStack catch a (\e -> maybe (throwM e) b $ f e)
+
+-- | Flipped 'catch'. See "Control.Exception"'s 'ControlException.handle'.
+handle :: (HasCallStack, MonadCatch m, Exception e) => (e -> m a) -> m a -> m a
+handle = flip (withFrozenCallStack catch)
+{-# INLINE handle #-}
+
+-- | Flipped 'catchIOError'
+handleIOError :: (HasCallStack, MonadCatch m) => (IOError -> m a) -> m a -> m a
+handleIOError = withFrozenCallStack handle
+
+-- | Flipped 'catchAll'
+handleAll :: (HasCallStack, MonadCatch m) => (SomeException -> m a) -> m a -> m a
+handleAll = withFrozenCallStack handle
+
+-- | Flipped 'catchIf'
+handleIf :: (HasCallStack, MonadCatch m, Exception e) => (e -> Bool) -> (e -> m a) -> m a -> m a
+handleIf f = flip (withFrozenCallStack catchIf f)
+
+-- | Flipped 'catchJust'. See "Control.Exception"'s 'ControlException.handleJust'.
+handleJust :: (HasCallStack, MonadCatch m, Exception e) => (e -> Maybe b) -> (b -> m a) -> m a -> m a
+handleJust f = flip (withFrozenCallStack catchJust f)
+{-# INLINE handleJust #-}
+
+-- | Similar to 'catch', but returns an 'Either' result. See "Control.Exception"'s
+-- 'Control.Exception.try'.
+try :: (HasCallStack, MonadCatch m, Exception e) => m a -> m (Either e a)
+try a = withFrozenCallStack catch (Right `liftM` a) (return . Left)
+
+-- | A variant of 'try' that takes an exception predicate to select
+-- which exceptions are caught. See "Control.Exception"'s 'ControlException.tryJust'
+tryJust :: (HasCallStack, MonadCatch m, Exception e) =>
+    (e -> Maybe b) -> m a -> m (Either b a)
+tryJust f a = withFrozenCallStack catch (Right `liftM` a) (\e -> maybe (throwM e) (return . Left) (f e))
+
+-- | Generalized version of 'ControlException.Handler'
+data Handler m a = forall e . ControlException.Exception e => Handler (e -> m a)
+
+instance Monad m => Functor (Handler m) where
+  fmap f (Handler h) = Handler (liftM f . h)
+
+-- | Catches different sorts of exceptions. See "Control.Exception"'s 'ControlException.catches'
+catches :: (HasCallStack, Foldable f, MonadCatch m) => m a -> f (Handler m a) -> m a
+catches a hs = withFrozenCallStack catch a handler
+  where
+    handler e = foldr probe (throwM e) hs
+      where
+        probe (Handler h) xs = maybe xs h (ControlException.fromException e)
+
+-- | Run an action only if an exception is thrown in the main action. The
+-- exception is not caught, simply rethrown.
+--
+-- /NOTE/ The action is only run if an /exception/ is thrown. If the monad
+-- supports other ways of aborting the computation, the action won't run if
+-- those other kinds of errors are thrown. See 'onError'.
+onException :: (HasCallStack, MonadCatch m) => m a -> m b -> m a
+onException action handler = withFrozenCallStack catchAll action (\e -> handler >> throwM e)
+
+-- | Run an action only if an error is thrown in the main action. Unlike
+-- 'onException', this works with every kind of error, not just exceptions. For
+-- example, if @f@ is an 'ExceptT' computation which aborts with a 'Left', the
+-- computation @onError f g@ will execute @g@, while @onException f g@ will not.
+--
+-- This distinction is only meaningful for monads which have multiple exit
+-- points, such as 'Except' and 'MaybeT'. For monads that only have a single
+-- exit point, there is no difference between 'onException' and 'onError',
+-- except that 'onError' has a more constrained type.
+--
+-- @since 0.10.0
+onError :: (HasCallStack, MonadMask m) => m a -> m b -> m a
+onError action handler = withFrozenCallStack bracketOnError (return ()) (const handler) (const action)
+
+-- | Generalized abstracted pattern of safe resource acquisition and release
+-- in the face of errors. The first action \"acquires\" some value, which
+-- is \"released\" by the second action at the end. The third action \"uses\"
+-- the value and its result is the result of the 'bracket'.
+--
+-- If an error is thrown during the use, the release still happens before the
+-- error is rethrown.
+--
+-- Note that this is essentially a type-specialized version of
+-- 'generalBracket'. This function has a more common signature (matching the
+-- signature from "Control.Exception"), and is often more convenient to use. By
+-- contrast, 'generalBracket' is more expressive, allowing us to implement
+-- other functions like 'bracketOnError'.
+bracket :: (HasCallStack, MonadMask m) => m a -> (a -> m c) -> (a -> m b) -> m b
+bracket acquire release = liftM fst . withFrozenCallStack generalBracket
+  acquire
+  (\a _exitCase -> release a)
+
+-- | Version of 'bracket' without any value being passed to the second and
+-- third actions.
+bracket_ :: (HasCallStack, MonadMask m) => m a -> m c -> m b -> m b
+bracket_ before after action = withFrozenCallStack bracket before (const after) (const action)
+
+-- | Perform an action with a finalizer action that is run, even if an
+-- error occurs.
+finally :: (HasCallStack, MonadMask m) => m a -> m b -> m a
+finally action finalizer = withFrozenCallStack bracket_ (return ()) finalizer action
+
+-- | Like 'bracket', but only performs the final action if an error is
+-- thrown by the in-between computation.
+bracketOnError :: (HasCallStack, MonadMask m) => m a -> (a -> m c) -> (a -> m b) -> m b
+bracketOnError acquire release = liftM fst . withFrozenCallStack generalBracket
+  acquire
+  (\a exitCase -> case exitCase of
+    ExitCaseSuccess _ -> return ()
+    _ -> do
+      _ <- release a
+      return ())
src/Control/Monad/Catch/Pure.hs view
@@ -1,225 +1,225 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}--#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702-{-# LANGUAGE Trustworthy #-}-#endif--#ifndef MIN_VERSION_transformers-#define MIN_VERSION_transformers(x,y,z) 1-#endif--#ifndef MIN_VERSION_mtl-#define MIN_VERSION_mtl(x,y,z) 1-#endif------------------------------------------------------------------------- |--- Copyright   :  (C) Edward Kmett 2013-2015, (c) Google Inc. 2012--- License     :  BSD-style (see the file LICENSE)--- Maintainer  :  Edward Kmett <ekmett@gmail.com>--- Stability   :  experimental--- Portability :  non-portable------ This module supplies a \'pure\' monad transformer that can be used for--- mock-testing code that throws exceptions, so long as those exceptions--- are always thrown with 'throwM'.------ Do not mix 'CatchT' with 'IO'. Choose one or the other for the--- bottom of your transformer stack!-----------------------------------------------------------------------module Control.Monad.Catch.Pure (-    -- * Transformer-    -- $transformer-    CatchT(..), Catch-  , runCatch-  , mapCatchT--  -- * Typeclass-  -- $mtl-  , module Control.Monad.Catch-  ) where--#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 706)-import Prelude hiding (foldr)-#else-import Prelude hiding (catch, foldr)-#endif--import Control.Applicative-import Control.Monad.Catch-import qualified Control.Monad.Fail as Fail-import Control.Monad.Fix (MonadFix(..))-import Control.Monad.IO.Class (MonadIO(..))-import Control.Monad (MonadPlus(..), ap, liftM)-import Control.Monad.Reader (MonadReader(..))-import Control.Monad.RWS (MonadRWS)-import Control.Monad.State (MonadState(..))-import Control.Monad.Trans.Class (MonadTrans(..))-import Control.Monad.Writer (MonadWriter(..))-#if __GLASGOW_HASKELL__ < 710-import Data.Foldable-import Data.Monoid (Monoid(..))-#endif-import Data.Functor.Identity-import Data.Traversable as Traversable----------------------------------------------------------------------------------- $mtl--- The mtl style typeclass------------------------------------------------------------------------------------------------------------------------------------------------------------------ $transformer--- The @transformers@-style monad transfomer----------------------------------------------------------------------------------- | Add 'Exception' handling abilities to a 'Monad'.------ This should /never/ be used in combination with 'IO'. Think of 'CatchT'--- as an alternative base monad for use with mocking code that solely throws--- exceptions via 'throwM'.------ Note: that 'IO' monad has these abilities already, so stacking 'CatchT' on top--- of it does not add any value and can possibly be confusing:------ >>> (error "Hello!" :: IO ()) `catch` (\(e :: ErrorCall) -> liftIO $ print e)--- Hello!------ >>> runCatchT $ (error "Hello!" :: CatchT IO ()) `catch` (\(e :: ErrorCall) -> liftIO $ print e)--- *** Exception: Hello!------ >>> runCatchT $ (throwM (ErrorCall "Hello!") :: CatchT IO ()) `catch` (\(e :: ErrorCall) -> liftIO $ print e)--- Hello!--newtype CatchT m a = CatchT { runCatchT :: m (Either SomeException a) }--type Catch = CatchT Identity--runCatch :: Catch a -> Either SomeException a-runCatch = runIdentity . runCatchT--instance Monad m => Functor (CatchT m) where-  fmap f (CatchT m) = CatchT (liftM (fmap f) m)--instance Monad m => Applicative (CatchT m) where-  pure a = CatchT (return (Right a))-  (<*>) = ap--instance Monad m => Monad (CatchT m) where-  return = pure-  CatchT m >>= k = CatchT $ m >>= \ea -> case ea of-    Left e -> return (Left e)-    Right a -> runCatchT (k a)-#if !(MIN_VERSION_base(4,13,0))-  fail = Fail.fail-#endif--instance Monad m => Fail.MonadFail (CatchT m) where-  fail = CatchT . return . Left . toException . userError--instance MonadFix m => MonadFix (CatchT m) where-  mfix f = CatchT $ mfix $ \a -> runCatchT $ f $ case a of-    Right r -> r-    _       -> error "empty mfix argument"--instance Foldable m => Foldable (CatchT m) where-  foldMap f (CatchT m) = foldMap (foldMapEither f) m where-    foldMapEither g (Right a) = g a-    foldMapEither _ (Left _) = mempty--instance (Monad m, Traversable m) => Traversable (CatchT m) where-  traverse f (CatchT m) = CatchT <$> Traversable.traverse (traverseEither f) m where-    traverseEither g (Right a) = Right <$> g a-    traverseEither _ (Left e) = pure (Left e)--instance Monad m => Alternative (CatchT m) where-  empty = mzero-  (<|>) = mplus--instance Monad m => MonadPlus (CatchT m) where-  mzero = CatchT $ return $ Left $ toException $ userError ""-  mplus (CatchT m) (CatchT n) = CatchT $ m >>= \ea -> case ea of-    Left _ -> n-    Right a -> return (Right a)--instance MonadTrans CatchT where-  lift m = CatchT $ do-    a <- m-    return $ Right a--instance MonadIO m => MonadIO (CatchT m) where-  liftIO m = CatchT $ do-    a <- liftIO m-    return $ Right a--instance Monad m => MonadThrow (CatchT m) where-  throwM = CatchT . return . Left . toException-instance Monad m => MonadCatch (CatchT m) where-  catch (CatchT m) c = CatchT $ m >>= \ea -> case ea of-    Left e -> case fromException e of-      Just e' -> runCatchT (c e')-      Nothing -> return (Left e)-    Right a -> return (Right a)--- | Note: This instance is only valid if the underlying monad has a single--- exit point!------ For example, @IO@ or @Either@ would be invalid base monads, but--- @Reader@ or @State@ would be acceptable.-instance Monad m => MonadMask (CatchT m) where-  mask a = a id-  uninterruptibleMask a = a id-  generalBracket acquire release use = CatchT $ do-    eresource <- runCatchT acquire-    case eresource of-      Left e -> return $ Left e-      Right resource -> do-        eb <- runCatchT (use resource)-        case eb of-          Left e -> runCatchT $ do-            _ <- release resource (ExitCaseException e)-            throwM e-          Right b -> runCatchT $ do-            c <- release resource (ExitCaseSuccess b)-            return (b, c)--instance MonadState s m => MonadState s (CatchT m) where-  get = lift get-  put = lift . put-#if MIN_VERSION_mtl(2,1,0)-  state = lift . state-#endif--instance MonadReader e m => MonadReader e (CatchT m) where-  ask = lift ask-  local f (CatchT m) = CatchT (local f m)--instance MonadWriter w m => MonadWriter w (CatchT m) where-  tell = lift . tell-  listen = mapCatchT $ \ m -> do-    (a, w) <- listen m-    return $! fmap (\ r -> (r, w)) a-  pass = mapCatchT $ \ m -> pass $ do-    a <- m-    return $! case a of-        Left  l      -> (Left  l, id)-        Right (r, f) -> (Right r, f)-#if MIN_VERSION_mtl(2,1,0)-  writer aw = CatchT (Right `liftM` writer aw)-#endif--instance MonadRWS r w s m => MonadRWS r w s (CatchT m)---- | Map the unwrapped computation using the given function.------ @'runCatchT' ('mapCatchT' f m) = f ('runCatchT' m)@-mapCatchT :: (m (Either SomeException a) -> n (Either SomeException b))-          -> CatchT m a-          -> CatchT n b-mapCatchT f m = CatchT $ f (runCatchT m)+{-# LANGUAGE CPP #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+
+#ifndef MIN_VERSION_transformers
+#define MIN_VERSION_transformers(x,y,z) 1
+#endif
+
+#ifndef MIN_VERSION_mtl
+#define MIN_VERSION_mtl(x,y,z) 1
+#endif
+
+--------------------------------------------------------------------
+-- |
+-- Copyright   :  (C) Edward Kmett 2013-2015, (c) Google Inc. 2012
+-- License     :  BSD-style (see the file LICENSE)
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- This module supplies a \'pure\' monad transformer that can be used for
+-- mock-testing code that throws exceptions, so long as those exceptions
+-- are always thrown with 'throwM'.
+--
+-- Do not mix 'CatchT' with 'IO'. Choose one or the other for the
+-- bottom of your transformer stack!
+--------------------------------------------------------------------
+
+module Control.Monad.Catch.Pure (
+    -- * Transformer
+    -- $transformer
+    CatchT(..), Catch
+  , runCatch
+  , mapCatchT
+
+  -- * Typeclass
+  -- $mtl
+  , module Control.Monad.Catch
+  ) where
+
+#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 706)
+import Prelude hiding (foldr)
+#else
+import Prelude hiding (catch, foldr)
+#endif
+
+import Control.Applicative
+import Control.Monad.Catch
+import qualified Control.Monad.Fail as Fail
+import Control.Monad.Fix (MonadFix(..))
+import Control.Monad.IO.Class (MonadIO(..))
+import Control.Monad (MonadPlus(..), ap, liftM)
+import Control.Monad.Reader (MonadReader(..))
+import Control.Monad.RWS (MonadRWS)
+import Control.Monad.State (MonadState(..))
+import Control.Monad.Trans.Class (MonadTrans(..))
+import Control.Monad.Writer (MonadWriter(..))
+#if __GLASGOW_HASKELL__ < 710
+import Data.Foldable
+import Data.Monoid (Monoid(..))
+#endif
+import Data.Functor.Identity
+import Data.Traversable as Traversable
+
+------------------------------------------------------------------------------
+-- $mtl
+-- The mtl style typeclass
+------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------
+-- $transformer
+-- The @transformers@-style monad transfomer
+------------------------------------------------------------------------------
+
+-- | Add 'Exception' handling abilities to a 'Monad'.
+--
+-- This should /never/ be used in combination with 'IO'. Think of 'CatchT'
+-- as an alternative base monad for use with mocking code that solely throws
+-- exceptions via 'throwM'.
+--
+-- Note: that 'IO' monad has these abilities already, so stacking 'CatchT' on top
+-- of it does not add any value and can possibly be confusing:
+--
+-- >>> (error "Hello!" :: IO ()) `catch` (\(e :: ErrorCall) -> liftIO $ print e)
+-- Hello!
+--
+-- >>> runCatchT $ (error "Hello!" :: CatchT IO ()) `catch` (\(e :: ErrorCall) -> liftIO $ print e)
+-- *** Exception: Hello!
+--
+-- >>> runCatchT $ (throwM (ErrorCall "Hello!") :: CatchT IO ()) `catch` (\(e :: ErrorCall) -> liftIO $ print e)
+-- Hello!
+
+newtype CatchT m a = CatchT { runCatchT :: m (Either SomeException a) }
+
+type Catch = CatchT Identity
+
+runCatch :: Catch a -> Either SomeException a
+runCatch = runIdentity . runCatchT
+
+instance Monad m => Functor (CatchT m) where
+  fmap f (CatchT m) = CatchT (liftM (fmap f) m)
+
+instance Monad m => Applicative (CatchT m) where
+  pure a = CatchT (return (Right a))
+  (<*>) = ap
+
+instance Monad m => Monad (CatchT m) where
+  return = pure
+  CatchT m >>= k = CatchT $ m >>= \ea -> case ea of
+    Left e -> return (Left e)
+    Right a -> runCatchT (k a)
+#if !(MIN_VERSION_base(4,13,0))
+  fail = Fail.fail
+#endif
+
+instance Monad m => Fail.MonadFail (CatchT m) where
+  fail = CatchT . return . Left . toException . userError
+
+instance MonadFix m => MonadFix (CatchT m) where
+  mfix f = CatchT $ mfix $ \a -> runCatchT $ f $ case a of
+    Right r -> r
+    _       -> error "empty mfix argument"
+
+instance Foldable m => Foldable (CatchT m) where
+  foldMap f (CatchT m) = foldMap (foldMapEither f) m where
+    foldMapEither g (Right a) = g a
+    foldMapEither _ (Left _) = mempty
+
+instance (Monad m, Traversable m) => Traversable (CatchT m) where
+  traverse f (CatchT m) = CatchT <$> Traversable.traverse (traverseEither f) m where
+    traverseEither g (Right a) = Right <$> g a
+    traverseEither _ (Left e) = pure (Left e)
+
+instance Monad m => Alternative (CatchT m) where
+  empty = mzero
+  (<|>) = mplus
+
+instance Monad m => MonadPlus (CatchT m) where
+  mzero = CatchT $ return $ Left $ toException $ userError ""
+  mplus (CatchT m) (CatchT n) = CatchT $ m >>= \ea -> case ea of
+    Left _ -> n
+    Right a -> return (Right a)
+
+instance MonadTrans CatchT where
+  lift m = CatchT $ do
+    a <- m
+    return $ Right a
+
+instance MonadIO m => MonadIO (CatchT m) where
+  liftIO m = CatchT $ do
+    a <- liftIO m
+    return $ Right a
+
+instance Monad m => MonadThrow (CatchT m) where
+  throwM = CatchT . return . Left . toException
+instance Monad m => MonadCatch (CatchT m) where
+  catch (CatchT m) c = CatchT $ m >>= \ea -> case ea of
+    Left e -> case fromException e of
+      Just e' -> runCatchT (c e')
+      Nothing -> return (Left e)
+    Right a -> return (Right a)
+-- | Note: This instance is only valid if the underlying monad has a single
+-- exit point!
+--
+-- For example, @IO@ or @Either@ would be invalid base monads, but
+-- @Reader@ or @State@ would be acceptable.
+instance Monad m => MonadMask (CatchT m) where
+  mask a = a id
+  uninterruptibleMask a = a id
+  generalBracket acquire release use = CatchT $ do
+    eresource <- runCatchT acquire
+    case eresource of
+      Left e -> return $ Left e
+      Right resource -> do
+        eb <- runCatchT (use resource)
+        case eb of
+          Left e -> runCatchT $ do
+            _ <- release resource (ExitCaseException e)
+            throwM e
+          Right b -> runCatchT $ do
+            c <- release resource (ExitCaseSuccess b)
+            return (b, c)
+
+instance MonadState s m => MonadState s (CatchT m) where
+  get = lift get
+  put = lift . put
+#if MIN_VERSION_mtl(2,1,0)
+  state = lift . state
+#endif
+
+instance MonadReader e m => MonadReader e (CatchT m) where
+  ask = lift ask
+  local f (CatchT m) = CatchT (local f m)
+
+instance MonadWriter w m => MonadWriter w (CatchT m) where
+  tell = lift . tell
+  listen = mapCatchT $ \ m -> do
+    (a, w) <- listen m
+    return $! fmap (\ r -> (r, w)) a
+  pass = mapCatchT $ \ m -> pass $ do
+    a <- m
+    return $! case a of
+        Left  l      -> (Left  l, id)
+        Right (r, f) -> (Right r, f)
+#if MIN_VERSION_mtl(2,1,0)
+  writer aw = CatchT (Right `liftM` writer aw)
+#endif
+
+instance MonadRWS r w s m => MonadRWS r w s (CatchT m)
+
+-- | Map the unwrapped computation using the given function.
+--
+-- @'runCatchT' ('mapCatchT' f m) = f ('runCatchT' m)@
+mapCatchT :: (m (Either SomeException a) -> n (Either SomeException b))
+          -> CatchT m a
+          -> CatchT n b
+mapCatchT f m = CatchT $ f (runCatchT m)
tests/Control/Monad/Catch/Tests.hs view
@@ -1,258 +1,258 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE CPP #-}--#if !(MIN_VERSION_transformers(0,6,0))-{-# OPTIONS_GHC -fno-warn-deprecations #-}-#endif--module Control.Monad.Catch.Tests (tests) where--#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ < 706)-import Prelude hiding (catch)-#endif--#if !(MIN_VERSION_base(4,8,0))-import Control.Applicative ((<*>))-#endif-import Control.Monad (unless)-import Data.Data (Data, Typeable)-import Data.IORef (newIORef, writeIORef, readIORef)--import Control.Monad.Trans.Class (lift)-import Control.Monad.Trans.Identity (IdentityT(..))-import Control.Monad.Reader (ReaderT(..))-import Control.Monad.Trans.Maybe (MaybeT(..))-import Control.Monad.Trans.Except (ExceptT(..), runExceptT)-import Control.Monad.STM (STM, atomically)---import Control.Monad.Cont (ContT(..))-import Test.Framework (Test, testGroup)-import Test.Framework.Providers.HUnit (testCase)-import Test.Framework.Providers.QuickCheck2 (testProperty)-import Test.QuickCheck (Property, ioProperty, once)-import Test.QuickCheck.Monadic (monadic, run, assert)-import qualified Control.Monad.State.Lazy as LazyState-import qualified Control.Monad.State.Strict as StrictState-import qualified Control.Monad.Writer.Lazy as LazyWriter-import qualified Control.Monad.Writer.Strict as StrictWriter-import qualified Control.Monad.RWS.Lazy as LazyRWS-import qualified Control.Monad.RWS.Strict as StrictRWS-#if !(MIN_VERSION_transformers(0,6,0))-import Control.Monad.Error (ErrorT(..))-import Control.Monad.List (ListT(..))-#endif--import Control.Monad.Catch-import Control.Monad.Catch.Pure--data TestException = TestException String-    deriving (Show, Eq, Data, Typeable)--instance Exception TestException--data MSpec m = MSpec-    { mspecName :: String-    , mspecRunner :: (m Property -> Property)-    }---- the @m Bool@ determines whether the @m ()@ has executed-data DetectableEffect m = DetectableEffect-    { detectableEffectMSpec :: MSpec m-    , detectableEffectEffectDetector :: m (m (), m Bool)-    }--data SomeMSpec = forall m. (MonadCatch m) => SomeMSpec (MSpec m)--data SomeDetectableEffect = forall m. (MonadMask m) => SomeDetectableEffect (DetectableEffect m)--testMonadCatch :: SomeMSpec -> Property-testMonadCatch (SomeMSpec MSpec { mspecRunner }) = monadic mspecRunner $-    run $ catch failure handler-  where-    failure = throwM (TestException "foo") >> error "testMonadCatch"-    handler (_ :: TestException) = return ()--testCatchJust :: SomeMSpec -> Property-testCatchJust (SomeMSpec MSpec { mspecRunner }) = monadic mspecRunner $ do-    nice <- run $ catchJust testException posFailure posHandler-    assert $ nice == ("pos", True)-    bad <- run $ catch (catchJust testException negFailure posHandler) negHandler-    assert $ bad == ("neg", True)-  where-    testException (TestException s) = if s == "pos" then Just True else Nothing-    posHandler x = return ("pos", x)-    negHandler (_ :: TestException) = return ("neg", True)-    posFailure = throwM (TestException "pos") >> error "testCatchJust pos"-    negFailure = throwM (TestException "neg") >> error "testCatchJust neg"--testDetectableEffect :: SomeDetectableEffect -> Property-testDetectableEffect (SomeDetectableEffect (DetectableEffect mspec effectDetector)) = do-    monadic (mspecRunner mspec) $ do-        effectWasPerformed <- run $ do-          (effect, detector) <- effectDetector-          _ <- runExceptT $ ExceptT (return $ Left ()) `finally` lift effect-          detector-        assert effectWasPerformed--tests :: Test-tests = testGroup "Control.Monad.Catch.Tests" $-   ([ mkMonadCatch-    , mkCatchJust-    ] <*> mspecs) ++-   ([ mkDetectableEffect-    ] <*> detectableEffects) ++-    [ testCase "ExceptT+Left" exceptTLeft-    , testCase "release error wins" releaseErrorWins-    ]-  where-    mspecs =-        [ SomeMSpec mspecIO-        , SomeMSpec mspecIdentityTIO-        , SomeMSpec mspecLazyStateTIO-        , SomeMSpec mspecStrictStateTIO-        , SomeMSpec mspecReaderTIO-        , SomeMSpec mspecLazyWriterTIO-        , SomeMSpec mspecStrictWriterTIO-        , SomeMSpec mspecLazyRWSTIO-        , SomeMSpec mspecStrictRWSTIO--        , SomeMSpec mspecMaybeTIO-#if !(MIN_VERSION_transformers(0,6,0))-        , SomeMSpec mspecErrorTIO-        , SomeMSpec mspecListTIO-#endif-        , SomeMSpec mspecSTM-        --, SomeMSpec mspecContTIO--        , SomeMSpec mspecCatchTIdentity-        , SomeMSpec mspecEitherSomeException-        ]--    mspecIO :: MSpec IO-    mspecIO = MSpec "IO" io--    mspecIdentityTIO :: MSpec (IdentityT IO)-    mspecIdentityTIO = MSpec "IdentityT IO" $ io . runIdentityT--    mspecLazyStateTIO :: MSpec (LazyState.StateT Bool IO)-    mspecLazyStateTIO = MSpec "LazyState.StateT IO" $ io . flip LazyState.evalStateT False--    mspecStrictStateTIO :: MSpec (StrictState.StateT Bool IO)-    mspecStrictStateTIO = MSpec "StrictState.StateT IO" $ io . flip StrictState.evalStateT False--    mspecReaderTIO :: MSpec (ReaderT () IO)-    mspecReaderTIO = MSpec "ReaderT IO" $ io . flip runReaderT ()--    mspecLazyWriterTIO :: MSpec (LazyWriter.WriterT () IO)-    mspecLazyWriterTIO = MSpec "LazyWriter.WriterT IO" $ io . fmap tfst . LazyWriter.runWriterT--    mspecStrictWriterTIO :: MSpec (StrictWriter.WriterT () IO)-    mspecStrictWriterTIO = MSpec "StrictWriter.WriterT IO" $ io . fmap tfst . StrictWriter.runWriterT--    mspecLazyRWSTIO :: MSpec (LazyRWS.RWST () () Bool IO)-    mspecLazyRWSTIO = MSpec "LazyRWS.RWST IO" $ \m -> io $ fmap tfst $ LazyRWS.evalRWST m () False--    mspecStrictRWSTIO :: MSpec (StrictRWS.RWST () () Bool IO)-    mspecStrictRWSTIO = MSpec "StrictRWS.RWST IO" $ \m -> io $ fmap tfst $ StrictRWS.evalRWST m () False--    mspecMaybeTIO :: MSpec (MaybeT IO)-    mspecMaybeTIO = MSpec "MaybeT IO" $ \m -> io $ fmap (maybe undefined id) (runMaybeT m)--#if !(MIN_VERSION_transformers(0,6,0))-    mspecErrorTIO :: MSpec (ErrorT String IO)-    mspecErrorTIO = MSpec "ErrorT IO" $ \m -> io $ fmap (either error id) (runErrorT m)--    mspecListTIO :: MSpec (ListT IO)-    mspecListTIO = MSpec "ListT IO" $ \m -> io $ fmap (foldr const undefined) (runListT m)-#endif--    mspecSTM :: MSpec STM-    mspecSTM = MSpec "STM" $ io . atomically--    --mspecContTIO :: MSpec (ContT () IO)-    --mspecContTIO = MSpec "ContT IO" $ \m -> io $ runContT m return--    mspecCatchTIdentity :: MSpec Catch-    mspecCatchTIdentity = MSpec "Catch" $ fromRight . runCatch--    mspecEitherSomeException :: MSpec (Either SomeException)-    mspecEitherSomeException = MSpec "Either SomeException" fromRight--    tfst :: (Property, ()) -> Property = fst-    fromRight (Left _) = error "fromRight"-    fromRight (Right a) = a-    io = ioProperty--    detectableEffects =-        [ SomeDetectableEffect $ detectableEffectIO-        , SomeDetectableEffect detectableEffectLazyStateTIO-        , SomeDetectableEffect detectableEffectStrictStateTIO-        , SomeDetectableEffect detectableEffectLazyRWSTIO-        , SomeDetectableEffect detectableEffectStrictRWSTIO-        ]--    detectableEffectIO :: DetectableEffect IO-    detectableEffectIO = DetectableEffect-      { detectableEffectMSpec = mspecIO-      , detectableEffectEffectDetector = do-          ref <- newIORef False-          return (writeIORef ref True, readIORef ref)-      }--    detectableEffectLazyStateTIO :: DetectableEffect (LazyState.StateT Bool IO)-    detectableEffectLazyStateTIO = DetectableEffect-      { detectableEffectMSpec = mspecLazyStateTIO-      , detectableEffectEffectDetector = do-          LazyState.put False-          return (LazyState.put True, LazyState.get)-      }--    detectableEffectStrictStateTIO :: DetectableEffect (StrictState.StateT Bool IO)-    detectableEffectStrictStateTIO = DetectableEffect-      { detectableEffectMSpec = mspecStrictStateTIO-      , detectableEffectEffectDetector = do-          StrictState.put False-          return (StrictState.put True, StrictState.get)-      }--    detectableEffectLazyRWSTIO :: DetectableEffect (LazyRWS.RWST () () Bool IO)-    detectableEffectLazyRWSTIO = DetectableEffect-      { detectableEffectMSpec = mspecLazyRWSTIO-      , detectableEffectEffectDetector = do-          LazyRWS.put False-          return (LazyRWS.put True, LazyRWS.get)-      }--    detectableEffectStrictRWSTIO :: DetectableEffect (StrictRWS.RWST () () Bool IO)-    detectableEffectStrictRWSTIO = DetectableEffect-      { detectableEffectMSpec = mspecStrictRWSTIO-      , detectableEffectEffectDetector = do-          StrictRWS.put False-          return (StrictRWS.put True, StrictRWS.get)-      }--    mkMonadCatch = mkMSpecTest "MonadCatch" testMonadCatch-    mkCatchJust = mkMSpecTest "catchJust" testCatchJust-    mkDetectableEffect = mkDetectableEffectTest "effect during release" testDetectableEffect--    mkMSpecTest :: String -> (SomeMSpec -> Property) -> SomeMSpec -> Test-    mkMSpecTest name test = \someMSpec@(SomeMSpec spec) ->-        testProperty (name ++ " " ++ mspecName spec) $ once $ test someMSpec--    mkDetectableEffectTest :: String -> (SomeDetectableEffect -> Property) -> SomeDetectableEffect -> Test-    mkDetectableEffectTest name test = \someDetectableEffect@(SomeDetectableEffect detectableEffect) ->-        let testName = name ++ " " ++ mspecName (detectableEffectMSpec detectableEffect)-        in testProperty testName $ once $ test someDetectableEffect--    exceptTLeft = do-      ref <- newIORef False-      Left () <- runExceptT $ ExceptT (return $ Left ()) `finally` lift (writeIORef ref True)-      val <- readIORef ref-      unless val $ error "Looks like cleanup didn't happen"--    -- if both 'use' and 'release' abort, the 'release' error should win-    releaseErrorWins = do-      Left val <- runExceptT $ ExceptT (return $ Left False) `finally` ExceptT (return $ Left True)-      unless val $ error "Looks like the 'use' error won"+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE CPP #-}
+
+#if !(MIN_VERSION_transformers(0,6,0))
+{-# OPTIONS_GHC -fno-warn-deprecations #-}
+#endif
+
+module Control.Monad.Catch.Tests (tests) where
+
+#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ < 706)
+import Prelude hiding (catch)
+#endif
+
+#if !(MIN_VERSION_base(4,8,0))
+import Control.Applicative ((<*>))
+#endif
+import Control.Monad (unless)
+import Data.Data (Data, Typeable)
+import Data.IORef (newIORef, writeIORef, readIORef)
+
+import Control.Monad.Trans.Class (lift)
+import Control.Monad.Trans.Identity (IdentityT(..))
+import Control.Monad.Reader (ReaderT(..))
+import Control.Monad.Trans.Maybe (MaybeT(..))
+import Control.Monad.Trans.Except (ExceptT(..), runExceptT)
+import Control.Monad.STM (STM, atomically)
+--import Control.Monad.Cont (ContT(..))
+import Test.Framework (Test, testGroup)
+import Test.Framework.Providers.HUnit (testCase)
+import Test.Framework.Providers.QuickCheck2 (testProperty)
+import Test.QuickCheck (Property, ioProperty, once)
+import Test.QuickCheck.Monadic (monadic, run, assert)
+import qualified Control.Monad.State.Lazy as LazyState
+import qualified Control.Monad.State.Strict as StrictState
+import qualified Control.Monad.Writer.Lazy as LazyWriter
+import qualified Control.Monad.Writer.Strict as StrictWriter
+import qualified Control.Monad.RWS.Lazy as LazyRWS
+import qualified Control.Monad.RWS.Strict as StrictRWS
+#if !(MIN_VERSION_transformers(0,6,0))
+import Control.Monad.Error (ErrorT(..))
+import Control.Monad.List (ListT(..))
+#endif
+
+import Control.Monad.Catch
+import Control.Monad.Catch.Pure
+
+data TestException = TestException String
+    deriving (Show, Eq, Data, Typeable)
+
+instance Exception TestException
+
+data MSpec m = MSpec
+    { mspecName :: String
+    , mspecRunner :: (m Property -> Property)
+    }
+
+-- the @m Bool@ determines whether the @m ()@ has executed
+data DetectableEffect m = DetectableEffect
+    { detectableEffectMSpec :: MSpec m
+    , detectableEffectEffectDetector :: m (m (), m Bool)
+    }
+
+data SomeMSpec = forall m. (MonadCatch m) => SomeMSpec (MSpec m)
+
+data SomeDetectableEffect = forall m. (MonadMask m) => SomeDetectableEffect (DetectableEffect m)
+
+testMonadCatch :: SomeMSpec -> Property
+testMonadCatch (SomeMSpec MSpec { mspecRunner }) = monadic mspecRunner $
+    run $ catch failure handler
+  where
+    failure = throwM (TestException "foo") >> error "testMonadCatch"
+    handler (_ :: TestException) = return ()
+
+testCatchJust :: SomeMSpec -> Property
+testCatchJust (SomeMSpec MSpec { mspecRunner }) = monadic mspecRunner $ do
+    nice <- run $ catchJust testException posFailure posHandler
+    assert $ nice == ("pos", True)
+    bad <- run $ catch (catchJust testException negFailure posHandler) negHandler
+    assert $ bad == ("neg", True)
+  where
+    testException (TestException s) = if s == "pos" then Just True else Nothing
+    posHandler x = return ("pos", x)
+    negHandler (_ :: TestException) = return ("neg", True)
+    posFailure = throwM (TestException "pos") >> error "testCatchJust pos"
+    negFailure = throwM (TestException "neg") >> error "testCatchJust neg"
+
+testDetectableEffect :: SomeDetectableEffect -> Property
+testDetectableEffect (SomeDetectableEffect (DetectableEffect mspec effectDetector)) = do
+    monadic (mspecRunner mspec) $ do
+        effectWasPerformed <- run $ do
+          (effect, detector) <- effectDetector
+          _ <- runExceptT $ ExceptT (return $ Left ()) `finally` lift effect
+          detector
+        assert effectWasPerformed
+
+tests :: Test
+tests = testGroup "Control.Monad.Catch.Tests" $
+   ([ mkMonadCatch
+    , mkCatchJust
+    ] <*> mspecs) ++
+   ([ mkDetectableEffect
+    ] <*> detectableEffects) ++
+    [ testCase "ExceptT+Left" exceptTLeft
+    , testCase "release error wins" releaseErrorWins
+    ]
+  where
+    mspecs =
+        [ SomeMSpec mspecIO
+        , SomeMSpec mspecIdentityTIO
+        , SomeMSpec mspecLazyStateTIO
+        , SomeMSpec mspecStrictStateTIO
+        , SomeMSpec mspecReaderTIO
+        , SomeMSpec mspecLazyWriterTIO
+        , SomeMSpec mspecStrictWriterTIO
+        , SomeMSpec mspecLazyRWSTIO
+        , SomeMSpec mspecStrictRWSTIO
+
+        , SomeMSpec mspecMaybeTIO
+#if !(MIN_VERSION_transformers(0,6,0))
+        , SomeMSpec mspecErrorTIO
+        , SomeMSpec mspecListTIO
+#endif
+        , SomeMSpec mspecSTM
+        --, SomeMSpec mspecContTIO
+
+        , SomeMSpec mspecCatchTIdentity
+        , SomeMSpec mspecEitherSomeException
+        ]
+
+    mspecIO :: MSpec IO
+    mspecIO = MSpec "IO" io
+
+    mspecIdentityTIO :: MSpec (IdentityT IO)
+    mspecIdentityTIO = MSpec "IdentityT IO" $ io . runIdentityT
+
+    mspecLazyStateTIO :: MSpec (LazyState.StateT Bool IO)
+    mspecLazyStateTIO = MSpec "LazyState.StateT IO" $ io . flip LazyState.evalStateT False
+
+    mspecStrictStateTIO :: MSpec (StrictState.StateT Bool IO)
+    mspecStrictStateTIO = MSpec "StrictState.StateT IO" $ io . flip StrictState.evalStateT False
+
+    mspecReaderTIO :: MSpec (ReaderT () IO)
+    mspecReaderTIO = MSpec "ReaderT IO" $ io . flip runReaderT ()
+
+    mspecLazyWriterTIO :: MSpec (LazyWriter.WriterT () IO)
+    mspecLazyWriterTIO = MSpec "LazyWriter.WriterT IO" $ io . fmap tfst . LazyWriter.runWriterT
+
+    mspecStrictWriterTIO :: MSpec (StrictWriter.WriterT () IO)
+    mspecStrictWriterTIO = MSpec "StrictWriter.WriterT IO" $ io . fmap tfst . StrictWriter.runWriterT
+
+    mspecLazyRWSTIO :: MSpec (LazyRWS.RWST () () Bool IO)
+    mspecLazyRWSTIO = MSpec "LazyRWS.RWST IO" $ \m -> io $ fmap tfst $ LazyRWS.evalRWST m () False
+
+    mspecStrictRWSTIO :: MSpec (StrictRWS.RWST () () Bool IO)
+    mspecStrictRWSTIO = MSpec "StrictRWS.RWST IO" $ \m -> io $ fmap tfst $ StrictRWS.evalRWST m () False
+
+    mspecMaybeTIO :: MSpec (MaybeT IO)
+    mspecMaybeTIO = MSpec "MaybeT IO" $ \m -> io $ fmap (maybe undefined id) (runMaybeT m)
+
+#if !(MIN_VERSION_transformers(0,6,0))
+    mspecErrorTIO :: MSpec (ErrorT String IO)
+    mspecErrorTIO = MSpec "ErrorT IO" $ \m -> io $ fmap (either error id) (runErrorT m)
+
+    mspecListTIO :: MSpec (ListT IO)
+    mspecListTIO = MSpec "ListT IO" $ \m -> io $ fmap (foldr const undefined) (runListT m)
+#endif
+
+    mspecSTM :: MSpec STM
+    mspecSTM = MSpec "STM" $ io . atomically
+
+    --mspecContTIO :: MSpec (ContT () IO)
+    --mspecContTIO = MSpec "ContT IO" $ \m -> io $ runContT m return
+
+    mspecCatchTIdentity :: MSpec Catch
+    mspecCatchTIdentity = MSpec "Catch" $ fromRight . runCatch
+
+    mspecEitherSomeException :: MSpec (Either SomeException)
+    mspecEitherSomeException = MSpec "Either SomeException" fromRight
+
+    tfst :: (Property, ()) -> Property = fst
+    fromRight (Left _) = error "fromRight"
+    fromRight (Right a) = a
+    io = ioProperty
+
+    detectableEffects =
+        [ SomeDetectableEffect $ detectableEffectIO
+        , SomeDetectableEffect detectableEffectLazyStateTIO
+        , SomeDetectableEffect detectableEffectStrictStateTIO
+        , SomeDetectableEffect detectableEffectLazyRWSTIO
+        , SomeDetectableEffect detectableEffectStrictRWSTIO
+        ]
+
+    detectableEffectIO :: DetectableEffect IO
+    detectableEffectIO = DetectableEffect
+      { detectableEffectMSpec = mspecIO
+      , detectableEffectEffectDetector = do
+          ref <- newIORef False
+          return (writeIORef ref True, readIORef ref)
+      }
+
+    detectableEffectLazyStateTIO :: DetectableEffect (LazyState.StateT Bool IO)
+    detectableEffectLazyStateTIO = DetectableEffect
+      { detectableEffectMSpec = mspecLazyStateTIO
+      , detectableEffectEffectDetector = do
+          LazyState.put False
+          return (LazyState.put True, LazyState.get)
+      }
+
+    detectableEffectStrictStateTIO :: DetectableEffect (StrictState.StateT Bool IO)
+    detectableEffectStrictStateTIO = DetectableEffect
+      { detectableEffectMSpec = mspecStrictStateTIO
+      , detectableEffectEffectDetector = do
+          StrictState.put False
+          return (StrictState.put True, StrictState.get)
+      }
+
+    detectableEffectLazyRWSTIO :: DetectableEffect (LazyRWS.RWST () () Bool IO)
+    detectableEffectLazyRWSTIO = DetectableEffect
+      { detectableEffectMSpec = mspecLazyRWSTIO
+      , detectableEffectEffectDetector = do
+          LazyRWS.put False
+          return (LazyRWS.put True, LazyRWS.get)
+      }
+
+    detectableEffectStrictRWSTIO :: DetectableEffect (StrictRWS.RWST () () Bool IO)
+    detectableEffectStrictRWSTIO = DetectableEffect
+      { detectableEffectMSpec = mspecStrictRWSTIO
+      , detectableEffectEffectDetector = do
+          StrictRWS.put False
+          return (StrictRWS.put True, StrictRWS.get)
+      }
+
+    mkMonadCatch = mkMSpecTest "MonadCatch" testMonadCatch
+    mkCatchJust = mkMSpecTest "catchJust" testCatchJust
+    mkDetectableEffect = mkDetectableEffectTest "effect during release" testDetectableEffect
+
+    mkMSpecTest :: String -> (SomeMSpec -> Property) -> SomeMSpec -> Test
+    mkMSpecTest name test = \someMSpec@(SomeMSpec spec) ->
+        testProperty (name ++ " " ++ mspecName spec) $ once $ test someMSpec
+
+    mkDetectableEffectTest :: String -> (SomeDetectableEffect -> Property) -> SomeDetectableEffect -> Test
+    mkDetectableEffectTest name test = \someDetectableEffect@(SomeDetectableEffect detectableEffect) ->
+        let testName = name ++ " " ++ mspecName (detectableEffectMSpec detectableEffect)
+        in testProperty testName $ once $ test someDetectableEffect
+
+    exceptTLeft = do
+      ref <- newIORef False
+      Left () <- runExceptT $ ExceptT (return $ Left ()) `finally` lift (writeIORef ref True)
+      val <- readIORef ref
+      unless val $ error "Looks like cleanup didn't happen"
+
+    -- if both 'use' and 'release' abort, the 'release' error should win
+    releaseErrorWins = do
+      Left val <- runExceptT $ ExceptT (return $ Left False) `finally` ExceptT (return $ Left True)
+      unless val $ error "Looks like the 'use' error won"
tests/Tests.hs view
@@ -1,10 +1,10 @@-module Main where--import Test.Framework (defaultMain)--import qualified Control.Monad.Catch.Tests--main :: IO ()-main = defaultMain-    [ Control.Monad.Catch.Tests.tests-    ]+module Main where
+
+import Test.Framework (defaultMain)
+
+import qualified Control.Monad.Catch.Tests
+
+main :: IO ()
+main = defaultMain
+    [ Control.Monad.Catch.Tests.tests
+    ]