diff --git a/Control/Monad/Cont/Class.hs b/Control/Monad/Cont/Class.hs
--- a/Control/Monad/Cont/Class.hs
+++ b/Control/Monad/Cont/Class.hs
@@ -66,8 +66,6 @@
 import Control.Monad.Trans.Writer.Lazy as LazyWriter
 import Control.Monad.Trans.Writer.Strict as StrictWriter
 
-import Data.Monoid
-
 class (Monad m) => MonadCont m where
     {- | @callCC@ (call-with-current-continuation)
     calls a function with the current continuation as its argument.
diff --git a/Control/Monad/Error.hs b/Control/Monad/Error.hs
--- a/Control/Monad/Error.hs
+++ b/Control/Monad/Error.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {- |
 Module      :  Control.Monad.Error
 Copyright   :  (c) Michael Weber <michael.weber@post.rwth-aachen.de> 2001,
@@ -32,7 +31,9 @@
   inspired by the Haskell Monad Template Library from
     Andy Gill (<http://web.cecs.pdx.edu/~andy/>)
 -}
-module Control.Monad.Error (
+module Control.Monad.Error
+  {-# DEPRECATED "Use Control.Monad.Except instead" #-}
+  (
     -- * Monads with error handling
     MonadError(..),
     Error,
@@ -55,9 +56,6 @@
 
 import Control.Monad
 import Control.Monad.Fix
-#if !(MIN_VERSION_base(4,6,0))
-import Control.Monad.Instances ()  -- deprecated from base-4.6
-#endif
 
 {- $customErrorExample
 Here is an example that demonstrates the use of a custom 'Error' data type with
diff --git a/Control/Monad/Error/Class.hs b/Control/Monad/Error/Class.hs
--- a/Control/Monad/Error/Class.hs
+++ b/Control/Monad/Error/Class.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {- |
 Module      :  Control.Monad.Error.Class
 Copyright   :  (c) Michael Weber <michael.weber@post.rwth-aachen.de> 2001,
@@ -32,7 +31,9 @@
   inspired by the Haskell Monad Template Library from
     Andy Gill (<http://web.cecs.pdx.edu/~andy/>)
 -}
-module Control.Monad.Error.Class (
+module Control.Monad.Error.Class
+  {-# DEPRECATED "Use Control.Monad.Except.Class instead" #-}
+  (
     Error(..),
     MonadError(..),
   ) where
@@ -52,11 +53,6 @@
 import Control.Monad.Trans
 
 import qualified Control.Exception
-#if !(MIN_VERSION_base(4,6,0))
-import Control.Monad.Instances ()  -- deprecated from base-4.6
-#endif
-import Data.Monoid
-import System.IO
 
 {- |
 The strategy of combining computations that can throw exceptions
diff --git a/Control/Monad/Except.hs b/Control/Monad/Except.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Except.hs
@@ -0,0 +1,148 @@
+{- |
+Module      :  Control.Monad.Except
+Copyright   :  (c) Michael Weber <michael.weber@post.rwth-aachen.de> 2001,
+               (c) Jeff Newbern 2003-2006,
+               (c) Andriy Palamarchuk 2006
+License     :  BSD-style (see the file LICENSE)
+
+Maintainer  :  ross@soi.city.ac.uk
+Stability   :  experimental
+Portability :  non-portable (type families)
+
+[Computation type:] Computations which may fail or throw exceptions.
+
+[Binding strategy:] Failure records information about the cause\/location
+of the failure. Failure values bypass the bound function,
+other values are used as inputs to the bound function.
+
+[Useful for:] Building computations from sequences of functions that may fail
+or using exception handling to structure error handling.
+
+[Zero and plus:] Zero is represented by an empty error and the plus operation
+executes its second argument if the first fails.
+
+[Example type:] @'Data.Either' String a@
+
+The Error monad (also called the Exception monad).
+-}
+
+{-
+  Rendered by Michael Weber <mailto:michael.weber@post.rwth-aachen.de>,
+  inspired by the Haskell Monad Template Library from
+    Andy Gill (<http://web.cecs.pdx.edu/~andy/>)
+-}
+module Control.Monad.Except (
+    -- * Monads with error handling
+    MonadError(..),
+    tryError,
+    withError,
+    -- * The ErrorT monad transformer
+    ExceptT(..),
+    runExceptT,
+    mapExceptT,
+    withExceptT,
+    module Control.Monad,
+    module Control.Monad.Fix,
+    module Control.Monad.Trans,
+    -- * Example 1: Custom Error Data Type
+    -- $customErrorExample
+
+    -- * Example 2: Using ExceptT Monad Transformer
+    -- $ExceptTExample
+  ) where
+
+import Control.Monad.Except.Class
+import Control.Monad.Trans
+import Control.Monad.Trans.Except (ExceptT(..), runExceptT, mapExceptT, withExceptT)
+
+import Control.Monad
+import Control.Monad.Fix
+
+-- | 'MonadError' analogue to the 'Control.Exception.try' function.
+tryError :: (MonadError m) => m a -> m (Either (ErrorType m) a)
+tryError action = (Right <$> action) `catchError` (pure . Left)
+
+-- | 'MonadError' analogue to the 'withExceptT' function.
+-- Modify the value (but not the type) of an error.
+-- The type is fixed because of the 'ErrorType' type family.
+withError :: (MonadError m) => (ErrorType m -> ErrorType m) -> m a -> m a
+withError f action = tryError action >>= either (throwError . f) pure
+
+{- $customErrorExample
+Here is an example that demonstrates the use of a custom 'Error' data type with
+the 'throwError' and 'catchError' exception mechanism from 'MonadError'.
+The example throws an exception if the user enters an empty string
+or a string longer than 5 characters. Otherwise it prints length of the string.
+
+>import Control.Monad.Except
+>
+>-- This is the type to represent length calculation error.
+>data LengthError = EmptyString  -- Entered string was empty.
+>          | StringTooLong Int   -- A string is longer than 5 characters.
+>                                -- Records a length of the string.
+>          | OtherError String   -- Other error, stores the problem description.
+>
+>-- Converts LengthError to a readable message.
+>instance Show LengthError where
+>  show EmptyString = "The string was empty!"
+>  show (StringTooLong len) =
+>      "The length of the string (" ++ (show len) ++ ") is bigger than 5!"
+>  show (OtherError msg) = msg
+>
+>-- For our monad type constructor, we use Either LengthError
+>-- which represents failure using Left LengthError
+>-- or a successful result of type a using Right a.
+>type LengthMonad = Either LengthError
+>
+>main = do
+>  putStrLn "Please enter a string:"
+>  s <- getLine
+>  reportResult (calculateLengthOrFail s)
+>
+>-- Attempts to calculate length and throws an error if the provided string is
+>-- empty or longer than 5 characters.
+>-- The processing is done in Either monad.
+>calculateLengthOrFail :: String -> LengthMonad Int
+>calculateLengthOrFail [] = throwError EmptyString
+>calculateLengthOrFail s | len > 5 = throwError (StringTooLong len)
+>                        | otherwise = return len
+>  where len = length s
+>
+>-- Prints result of the string length calculation.
+>reportResult :: LengthMonad Int -> IO ()
+>reportResult (Right len) = putStrLn ("The length of the string is " ++ (show len))
+>reportResult (Left e) = putStrLn ("Length calculation failed with error: " ++ (show e))
+-}
+
+{- $ExceptTExample
+@'ErrorT'@ monad transformer can be used to add error handling to another monad.
+Here is an example how to combine it with an @IO@ monad:
+
+>import Control.Monad.Except
+>
+>-- An IO monad which can return String failure.
+>-- It is convenient to define the monad type of the combined monad,
+>-- especially if we combine more monad transformers.
+>type LengthMonad = ExceptT String IO
+>
+>main = do
+>  -- runExceptT removes the ExceptT wrapper
+>  r <- runExceptT calculateLength
+>  reportResult r
+>
+>-- Asks user for a non-empty string and returns its length.
+>-- Throws an error if user enters an empty string.
+>calculateLength :: LengthMonad Int
+>calculateLength = do
+>  -- all the IO operations have to be lifted to the IO monad in the monad stack
+>  liftIO $ putStrLn "Please enter a non-empty string: "
+>  s <- liftIO getLine
+>  if null s
+>    then throwError "The string was empty!"
+>    else return $ length s
+>
+>-- Prints result of the string length calculation.
+>reportResult :: Either String Int -> IO ()
+>reportResult (Right len) = putStrLn ("The length of the string is " ++ (show len))
+>reportResult (Left e) = putStrLn ("Length calculation failed with error: " ++ (show e))
+-}
diff --git a/Control/Monad/Except/Class.hs b/Control/Monad/Except/Class.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Except/Class.hs
@@ -0,0 +1,151 @@
+{- |
+Module      :  Control.Monad.Except.Class
+Copyright   :  (c) Michael Weber <michael.weber@post.rwth-aachen.de> 2001,
+               (c) Jeff Newbern 2003-2006,
+               (c) Andriy Palamarchuk 2006
+License     :  BSD-style (see the file LICENSE)
+
+Maintainer  :  ross@soi.city.ac.uk
+Stability   :  experimental
+Portability :  non-portable (type families)
+
+[Computation type:] Computations which may fail or throw exceptions.
+
+[Binding strategy:] Failure records information about the cause\/location
+of the failure. Failure values bypass the bound function,
+other values are used as inputs to the bound function.
+
+[Useful for:] Building computations from sequences of functions that may fail
+or using exception handling to structure error handling.
+
+[Zero and plus:] Zero is represented by an empty error and the plus operation
+executes its second argument if the first fails.
+
+[Example type:] @'Either' 'String' a@
+
+The Error monad (also called the Exception monad).
+-}
+
+{-
+  Rendered by Michael Weber <mailto:michael.weber@post.rwth-aachen.de>,
+  inspired by the Haskell Monad Template Library from
+    Andy Gill (<http://web.cecs.pdx.edu/~andy/>)
+-}
+module Control.Monad.Except.Class (
+    MonadError(..),
+  ) where
+
+import Control.Monad.Trans.Except (ExceptT)
+import qualified Control.Monad.Trans.Except as ExceptT (throwE, catchE)
+import Control.Monad.Trans.Identity as Identity
+import Control.Monad.Trans.List as List
+import Control.Monad.Trans.Maybe as Maybe
+import Control.Monad.Trans.Reader as Reader
+import Control.Monad.Trans.RWS.Lazy as LazyRWS
+import Control.Monad.Trans.RWS.Strict as StrictRWS
+import Control.Monad.Trans.State.Lazy as LazyState
+import Control.Monad.Trans.State.Strict as StrictState
+import Control.Monad.Trans.Writer.Lazy as LazyWriter
+import Control.Monad.Trans.Writer.Strict as StrictWriter
+import Control.Monad.Trans
+
+import qualified Control.Exception
+
+{- |
+The strategy of combining computations that can throw exceptions
+by bypassing bound functions
+from the point an exception is thrown to the point that it is handled.
+
+Is parameterized over the type of error information and
+the monad type constructor.
+It is common to use @'Data.Either' String@ as the monad type constructor
+for an error monad in which error descriptions take the form of strings.
+In that case and many other common cases the resulting monad is already defined
+as an instance of the 'MonadError' class.
+You can also define your own a monad type constructor
+other than @'Data.Either' e@, in which case you will have to explicitly define
+an instance of the 'MonadError' class.
+-}
+class (Monad m) => MonadError m where
+    type ErrorType m
+
+    -- | Is used within a monadic computation to begin exception processing.
+    throwError :: ErrorType m -> m a
+
+    {- |
+    A handler function to handle previous errors and return to normal execution.
+    A common idiom is:
+
+    > do { action1; action2; action3 } `catchError` handler
+
+    where the @action@ functions can call 'throwError'.
+    Note that @handler@ and the do-block must have the same return type.
+    -}
+    catchError :: m a -> (ErrorType m -> m a) -> m a
+
+instance MonadError IO where
+    type ErrorType IO = IOError
+    throwError = ioError
+    catchError = Control.Exception.catch
+
+-- ---------------------------------------------------------------------------
+-- Our parameterizable error monad
+
+instance MonadError (Either e) where
+    type ErrorType (Either e) = e
+    throwError             = Left
+    Left  l `catchError` h = h l
+    Right r `catchError` _ = Right r
+
+instance (Monad m) => MonadError (ExceptT e m) where
+    type ErrorType (ExceptT e m) = e
+    throwError = ExceptT.throwE
+    catchError = ExceptT.catchE
+
+-- ---------------------------------------------------------------------------
+-- Instances for other mtl transformers
+
+instance (MonadError m) => MonadError (IdentityT m) where
+    type ErrorType (IdentityT m) = ErrorType m
+    throwError = lift . throwError
+    catchError = Identity.liftCatch catchError
+
+instance (MonadError m) => MonadError (MaybeT m) where
+    type ErrorType (MaybeT m) = ErrorType m
+    throwError = lift . throwError
+    catchError = Maybe.liftCatch catchError
+
+instance (MonadError m) => MonadError (ReaderT r m) where
+    type ErrorType (ReaderT r m) = ErrorType m
+    throwError = lift . throwError
+    catchError = Reader.liftCatch catchError
+
+instance (Monoid w, MonadError m) => MonadError (LazyRWS.RWST r w s m) where
+    type ErrorType (LazyRWS.RWST r w s m) = ErrorType m
+    throwError = lift . throwError
+    catchError = LazyRWS.liftCatch catchError
+
+instance (Monoid w, MonadError m) => MonadError (StrictRWS.RWST r w s m) where
+    type ErrorType (StrictRWS.RWST r w s m) = ErrorType m
+    throwError = lift . throwError
+    catchError = StrictRWS.liftCatch catchError
+
+instance (MonadError m) => MonadError (LazyState.StateT s m) where
+    type ErrorType (LazyState.StateT s m) = ErrorType m
+    throwError = lift . throwError
+    catchError = LazyState.liftCatch catchError
+
+instance (MonadError m) => MonadError (StrictState.StateT s m) where
+    type ErrorType (StrictState.StateT s m) = ErrorType m
+    throwError = lift . throwError
+    catchError = StrictState.liftCatch catchError
+
+instance (Monoid w, MonadError m) => MonadError (LazyWriter.WriterT w m) where
+    type ErrorType (LazyWriter.WriterT w m) = ErrorType m
+    throwError = lift . throwError
+    catchError = LazyWriter.liftCatch catchError
+
+instance (Monoid w, MonadError m) => MonadError (StrictWriter.WriterT w m) where
+    type ErrorType (StrictWriter.WriterT w m) = ErrorType m
+    throwError = lift . throwError
+    catchError = StrictWriter.liftCatch catchError
diff --git a/Control/Monad/List.hs b/Control/Monad/List.hs
--- a/Control/Monad/List.hs
+++ b/Control/Monad/List.hs
@@ -13,7 +13,9 @@
 --
 -----------------------------------------------------------------------------
 
-module Control.Monad.List (
+module Control.Monad.List
+  {-# DEPRECATED "This transformer is invalid on most monads" #-}
+  (
     ListT(..),
     mapListT,
     module Control.Monad,
diff --git a/Control/Monad/RWS/Class.hs b/Control/Monad/RWS/Class.hs
--- a/Control/Monad/RWS/Class.hs
+++ b/Control/Monad/RWS/Class.hs
@@ -36,20 +36,18 @@
 import Control.Monad.Trans.RWS.Lazy as Lazy (RWST)
 import qualified Control.Monad.Trans.RWS.Strict as Strict (RWST)
 
-import Data.Monoid
-
 class (Monoid (WriterType m), MonadReader m, MonadWriter m, MonadState m) =>
     MonadRWS m
 
 instance (Monoid w, Monad m) => MonadRWS (Lazy.RWST r w s m)
 
 instance (Monoid w, Monad m) => MonadRWS (Strict.RWST r w s m)
- 
+
 ---------------------------------------------------------------------------
 -- Instances for other mtl transformers
- 
+
 instance (Error e, MonadRWS m) => MonadRWS (ErrorT e m)
- 
+
 instance (MonadRWS m) => MonadRWS (IdentityT m)
- 
+
 instance (MonadRWS m) => MonadRWS (MaybeT m)
diff --git a/Control/Monad/Reader/Class.hs b/Control/Monad/Reader/Class.hs
--- a/Control/Monad/Reader/Class.hs
+++ b/Control/Monad/Reader/Class.hs
@@ -30,8 +30,7 @@
 than using the 'Control.Monad.State.State' monad.
 
   Inspired by the paper
-  /Functional Programming with Overloading and
-      Higher-Order Polymorphism/, 
+  /Functional Programming with Overloading and Higher-Order Polymorphism/,
     Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>)
     Advanced School of Functional Programming, 1995.
 -}
@@ -55,8 +54,6 @@
 import Control.Monad.Trans.Writer.Lazy as Lazy
 import Control.Monad.Trans.Writer.Strict as Strict
 import Control.Monad.Trans
-
-import Data.Monoid
 
 -- ----------------------------------------------------------------------------
 -- class MonadReader
diff --git a/Control/Monad/State/Class.hs b/Control/Monad/State/Class.hs
--- a/Control/Monad/State/Class.hs
+++ b/Control/Monad/State/Class.hs
@@ -39,8 +39,6 @@
 import Control.Monad.Trans.Writer.Lazy as Lazy
 import Control.Monad.Trans.Writer.Strict as Strict
 
-import Data.Monoid
-
 -- ---------------------------------------------------------------------------
 -- | /get/ returns the state from the internals of the monad.
 --
diff --git a/Control/Monad/Writer/Class.hs b/Control/Monad/Writer/Class.hs
--- a/Control/Monad/Writer/Class.hs
+++ b/Control/Monad/Writer/Class.hs
@@ -40,8 +40,6 @@
         WriterT, tell, listen, pass)
 import Control.Monad.Trans (lift)
 
-import Data.Monoid
-
 -- ---------------------------------------------------------------------------
 -- MonadWriter class
 --
diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,2 +0,0 @@
-import Distribution.Simple
-main = defaultMain
diff --git a/changelog.md b/changelog.md
new file mode 100644
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,53 @@
+## 0.2.0.0
+
+Added new modules `Control.Monad.Except` and
+`Control.Monad.Except.Class`
+
+Deprecated modules `Control.Monad.Error` and
+`Control.Monad.Error.Class` in favor of the new `Except`
+modules, following what `transformers-0.4.0.0` did.
+
+Deprecated module `Control.Monad.List`, following what
+`transformers-0.5.3.0` did.
+
+Contributors: Ross Paterson and Chris Martin
+
+Published by: Chris Martin
+
+Date: 2023-07-10
+
+## 0.1.0.3
+
+Published by: Ross Paterson
+
+Date: 2016-06-08
+
+## 0.1.0.2
+
+Published by: Ross Paterson
+
+Date: 2014-04-19
+
+## 0.1.0.1
+
+Published by: Ross Paterson
+
+Date: 2012-09-16
+
+## 0.1.0.0
+
+Published by: Ross Paterson
+
+Date: 2010-03-26
+
+## 0.0.0.1
+
+Published by: Ross Paterson
+
+Date: 2009-03-22
+
+## 0.0.0.0
+
+Published by: Ross Paterson
+
+Date: 2009-01-10
diff --git a/monads-tf.cabal b/monads-tf.cabal
--- a/monads-tf.cabal
+++ b/monads-tf.cabal
@@ -1,28 +1,29 @@
+cabal-version: 3.0
+
 name:         monads-tf
-version:      0.1.0.3
-license:      BSD3
+version:      0.2.0.0
+license:      BSD-3-Clause
 license-file: LICENSE
 author:       Andy Gill
-maintainer:   Ross Paterson <ross@soi.city.ac.uk>
+maintainer:   Ross Paterson <ross@soi.city.ac.uk>,
+              Chris Martin <chris@typeclasses.com>
 category:     Control
 synopsis:     Monad classes, using type families
+homepage:     https://github.com/typeclasses/monads-tf
 description:
-    Monad classes using type families, with instances for various
-    monad transformers, inspired by the paper /Functional Programming
-    with Overloading and Higher-Order Polymorphism/, by Mark P
-    Jones, in /Advanced School of Functional Programming/, 1995
-    (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>).
-    .
-    This package is almost a compatible replacement for the @mtl-tf@ package.
-build-type: Simple
-cabal-version: >= 1.2.3
+    Monad classes using type families, with instances for
+    various monad transformers.
 
+extra-source-files: *.md
+
 library
   exposed-modules:
     Control.Monad.Cont
     Control.Monad.Cont.Class
     Control.Monad.Error
     Control.Monad.Error.Class
+    Control.Monad.Except
+    Control.Monad.Except.Class
     Control.Monad.Identity
     Control.Monad.List
     Control.Monad.RWS
@@ -40,8 +41,11 @@
     Control.Monad.Writer.Class
     Control.Monad.Writer.Lazy
     Control.Monad.Writer.Strict
-  build-depends: base < 6, transformers >= 0.2.0.0 && < 0.6
-  extensions:
-    FlexibleContexts
+  build-depends:
+    , base ^>= 4.16 || ^>= 4.17 || ^>= 4.18
+    , transformers ^>= 0.5.6
+  default-extensions:
     TypeFamilies
-  exposed: False
+  default-language: GHC2021
+  ghc-options: -Wall
+  hs-source-dirs: .
diff --git a/readme.md b/readme.md
new file mode 100644
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,8 @@
+Monad classes using type families, with instances for various monad transformers,
+inspired by the paper
+[Functional Programming with Overloading and Higher-Order Polymorphism][paper],
+by Mark P Jones, in *Advanced School of Functional Programming*, 1995.
+
+This package is almost a compatible replacement for the `mtl-tf` package.
+
+  [paper]: https://web.cecs.pdx.edu/~mpj/pubs/springschool.html
