diff --git a/Control/Applicative/Backwards.hs b/Control/Applicative/Backwards.hs
--- a/Control/Applicative/Backwards.hs
+++ b/Control/Applicative/Backwards.hs
@@ -41,7 +41,7 @@
 import Prelude hiding (foldr, foldr1, foldl, foldl1, null, length)
 import Control.Applicative
 import Data.Foldable
-#if !(MIN_VERSION_base(4,8,0))
+#if !(MIN_VERSION_base(4,8,0)) || defined(__MHS__)
 import Data.Traversable (Traversable(traverse, sequenceA))
 #endif
 
diff --git a/Control/Applicative/Lift.hs b/Control/Applicative/Lift.hs
--- a/Control/Applicative/Lift.hs
+++ b/Control/Applicative/Lift.hs
@@ -39,7 +39,7 @@
 
 import Control.Applicative
 import Data.Functor.Constant
-#if !(MIN_VERSION_base(4,8,0))
+#if !(MIN_VERSION_base(4,8,0)) || defined(__MHS__)
 import Data.Foldable (Foldable(foldMap))
 import Data.Monoid (Monoid(..))
 import Data.Traversable (Traversable(traverse))
diff --git a/Control/Monad/Signatures.hs b/Control/Monad/Signatures.hs
--- a/Control/Monad/Signatures.hs
+++ b/Control/Monad/Signatures.hs
@@ -27,23 +27,27 @@
 -- introduced in "Control.Monad.Trans.Cont".
 -- Any lifting function @liftCallCC@ should satisfy
 --
--- * @'Control.Monad.Trans.Class.lift' (f k) = f' ('Control.Monad.Trans.Class.lift' . k) => 'Control.Monad.Trans.Class.lift' (cf f) = liftCallCC cf f'@
+-- @'Control.Monad.Trans.Class.lift' (f k) = f' ('Control.Monad.Trans.Class.lift' . k) => 'Control.Monad.Trans.Class.lift' (cf f) = liftCallCC cf f'@
 --
+-- This implies that on entry to the continuation any outer monad
+-- transformer effect inside @callCC@ will have been rolled back.
 type CallCC m a b = ((a -> m b) -> m a) -> m a
 
 -- | Signature of the @catchE@ operation,
 -- introduced in "Control.Monad.Trans.Except".
 -- Any lifting function @liftCatch@ should satisfy
 --
--- * @'Control.Monad.Trans.Class.lift' (cf m f) = liftCatch ('Control.Monad.Trans.Class.lift' . cf) ('Control.Monad.Trans.Class.lift' f)@
+-- @'Control.Monad.Trans.Class.lift' (cf m h) = liftCatch cf ('Control.Monad.Trans.Class.lift' m) ('Control.Monad.Trans.Class.lift' . h)@
 --
+-- This implies that on entry to the handler function any outer monad
+-- transformer effect inside @catchE@ will have been rolled back.
 type Catch e m a = m a -> (e -> m a) -> m a
 
 -- | Signature of the @listen@ operation,
 -- introduced in "Control.Monad.Trans.Writer".
 -- Any lifting function @liftListen@ should satisfy
 --
--- * @'Control.Monad.Trans.Class.lift' . liftListen = liftListen . 'Control.Monad.Trans.Class.lift'@
+-- @'Control.Monad.Trans.Class.lift' . liftListen = liftListen . 'Control.Monad.Trans.Class.lift'@
 --
 type Listen w m a = m a -> m (a, w)
 
@@ -51,6 +55,6 @@
 -- introduced in "Control.Monad.Trans.Writer".
 -- Any lifting function @liftPass@ should satisfy
 --
--- * @'Control.Monad.Trans.Class.lift' . liftPass = liftPass . 'Control.Monad.Trans.Class.lift'@
+-- @'Control.Monad.Trans.Class.lift' . liftPass = liftPass . 'Control.Monad.Trans.Class.lift'@
 --
 type Pass w m a =  m (a, w -> w) -> m a
diff --git a/Control/Monad/Trans/Accum.hs b/Control/Monad/Trans/Accum.hs
--- a/Control/Monad/Trans/Accum.hs
+++ b/Control/Monad/Trans/Accum.hs
@@ -18,10 +18,12 @@
 --
 -- The lazy 'AccumT' monad transformer, which adds accumulation
 -- capabilities (such as declarations or document patches) to a given monad.
+-- Each computation has access to the combination of the input environment
+-- and outputs added so far, and returns the outputs added.
 --
--- This monad transformer provides append-only accumulation
--- during the computation. For more general access, use
--- "Control.Monad.Trans.State" instead.
+-- In applications requiring only the ability to accumulate an output and
+-- to inspect the output so far, it would be considerably more efficient
+-- to use "Control.Monad.Trans.State" instead.
 -----------------------------------------------------------------------------
 
 module Control.Monad.Trans.Accum (
@@ -33,8 +35,7 @@
     evalAccum,
     mapAccum,
     -- * The AccumT monad transformer
-    AccumT(AccumT),
-    runAccumT,
+    AccumT(..),
     execAccumT,
     evalAccumT,
     mapAccumT,
@@ -76,10 +77,19 @@
 #endif
 
 -- ---------------------------------------------------------------------------
--- | An accumulation monad parameterized by the type @w@ of output to accumulate.
+-- | An accumulation monad (non-strict) parameterized by the type @w@
+-- of output to accumulate.
 --
--- The 'return' function produces the output 'mempty', while @>>=@
--- combines the outputs of the subcomputations using 'mappend'.
+-- This monad is a more complex extension of both the reader and writer
+-- monads.  The 'return' function produces the output 'mempty', while @m
+-- '>>=' k@ uses the output of @m@ both to extend the initial environment
+-- of @k@ and to combine with the output of @k@:
+--
+-- <<images/bind-AccumT.svg>>
+--
+-- In applications requiring only the ability to accumulate an output and
+-- to inspect the output so far, it would be considerably more efficient
+-- to use a state monad.
 type Accum w = AccumT w Identity
 
 -- | Construct an accumulation computation from a (result, output) pair.
@@ -124,25 +134,32 @@
 --
 --   * @m@ - The inner monad.
 --
--- The 'return' function produces the output 'mempty', while @>>=@
--- combines the outputs of the subcomputations using 'mappend'.
+-- This monad transformer is a more complex extension of both the reader
+-- and writer monad transformers.  The 'return' function produces the
+-- output 'mempty', while @m '>>=' k@ uses the output of @m@ both to
+-- extend the initial environment of @k@ and to combine with the output
+-- of @k@:
 --
--- This monad transformer is similar to both state and writer monad transformers.
--- Thus it can be seen as
+-- <<images/bind-AccumT.svg>>
 --
---  * a restricted append-only version of a state monad transformer or
+-- In applications requiring only the ability to accumulate an output and
+-- to inspect the output so far, it would be considerably more efficient
+-- to use a state monad transformer.
 --
---  * a writer monad transformer with the extra ability to read all previous output.
-newtype AccumT w m a = AccumT (w -> m (a, w))
+-- @AccumT w m@ is strict if and only if @m@ is.
+newtype AccumT w m a = AccumT {
+    -- | Unwrap an accumulation computation.  For example, in the call
+    --
+    -- @    (value, locals) <- runAccumT action globals@
+    --
+    -- the action is fed an initial environment @globals@, and @locals@ is
+    -- the sum of all arguments to calls of 'add' executed by the action.
+    runAccumT :: w -> m (a, w)
+    }
 #if __GLASGOW_HASKELL__ >= 704
     deriving (Generic)
 #endif
 
--- | Unwrap an accumulation computation.
-runAccumT :: AccumT w m a -> w -> m (a, w)
-runAccumT (AccumT f) = f
-{-# INLINE runAccumT #-}
-
 -- | Extract the output from an accumulation computation.
 --
 -- * @'execAccumT' m w = 'liftM' 'snd' ('runAccumT' m w)@
@@ -152,8 +169,8 @@
     return w'
 {-# INLINE execAccumT #-}
 
--- | Evaluate an accumulation computation with the given initial output history
--- and return the final value, discarding the final output.
+-- | Evaluate an accumulation computation with the given initial output
+-- history and return the final value, discarding the final output.
 --
 -- * @'evalAccumT' m w = 'liftM' 'fst' ('runAccumT' m w)@
 evalAccumT :: (Monad m, Monoid w) => AccumT w m a -> w -> m a
@@ -162,8 +179,8 @@
     return a
 {-# INLINE evalAccumT #-}
 
--- | Map both the return value and output of a computation using
--- the given function.
+-- | Map both the return value and output of a computation using the
+-- given function.
 --
 -- * @'runAccumT' ('mapAccumT' f m) = f . 'runAccumT' m@
 mapAccumT :: (m (a, w) -> n (b, w)) -> AccumT w m a -> AccumT w n b
@@ -262,6 +279,9 @@
 {-# INLINE liftCallCC' #-}
 
 -- | Lift a @catchE@ operation to the new monad.
+-- The uniformity property (see "Control.Monad.Signatures") implies that
+-- the lifted @catchE@ discards any output from the body on entering
+-- the handler.
 liftCatch :: Catch e m (a, w) -> Catch e (AccumT w m) a
 liftCatch catchE m h =
     AccumT $ \ w -> runAccumT m w `catchE` \ e -> runAccumT (h e) w
diff --git a/Control/Monad/Trans/Class.hs b/Control/Monad/Trans/Class.hs
--- a/Control/Monad/Trans/Class.hs
+++ b/Control/Monad/Trans/Class.hs
@@ -87,15 +87,18 @@
     lift :: (Monad m) => m a -> t m a
 
 {- $conventions
-Most monad transformer modules include the special case of applying
-the transformer to 'Data.Functor.Identity.Identity'.  For example,
+All monad transformer modules except 'Control.Monad.Trans.Maybe'
+include the special case of applying the transformer
+to 'Data.Functor.Identity.Identity'.  For example,
 @'Control.Monad.Trans.State.Lazy.State' s@ is an abbreviation for
 @'Control.Monad.Trans.State.Lazy.StateT' s 'Data.Functor.Identity.Identity'@.
+As a consequence, operations defined on the monad transformer can also
+be used on this special case.
 
 Each monad transformer also comes with an operation @run@/XXX/@T@ to
 unwrap the transformer, exposing a computation of the inner monad.
-(Currently these functions are defined as field labels, but in the next
-major release they will be separate functions.)
+(Currently these functions are defined as field labels, but in a future
+major release they may be separate functions.)
 
 All of the monad transformers except 'Control.Monad.Trans.Cont.ContT'
 and 'Control.Monad.Trans.Cont.SelectT' are functors on the category
@@ -134,7 +137,7 @@
 >>> undefined >> print 2
 *** Exception: Prelude.undefined
 
-However the monads 'Data.Functor.Identity.Identity' and @(->) a@ are not:
+However, the monads 'Data.Functor.Identity.Identity' and @(->) a@ are not:
 
 >>> undefined >> Identity 2
 Identity 2
@@ -143,7 +146,7 @@
 
 In a strict monad you know when each action is executed, but the monad
 is not necessarily strict in the return value, or in other components
-of the monad, such as a state.  However you can use 'seq' to create
+of the monad, such as a state.  However, you can use 'seq' to create
 an action that is strict in the component you want evaluated.
 -}
 
diff --git a/Control/Monad/Trans/Cont.hs b/Control/Monad/Trans/Cont.hs
--- a/Control/Monad/Trans/Cont.hs
+++ b/Control/Monad/Trans/Cont.hs
@@ -64,7 +64,7 @@
 #endif
 
 {- |
-Continuation monad.
+The continuation monad, which is non-strict.
 @Cont r a@ is a CPS ("continuation-passing style") computation that produces an
 intermediate result of type @a@ within a CPS computation whose final result type
 is @r@.
@@ -139,6 +139,8 @@
 --
 -- 'ContT' is not a functor on the category of monads, and many operations
 -- cannot be lifted through it.
+--
+-- @ContT r m@ is strict if and only if @m@ is.
 newtype ContT r m a = ContT { runContT :: (a -> m r) -> m r }
 #if __GLASGOW_HASKELL__ >= 704
     deriving (Generic)
diff --git a/Control/Monad/Trans/Except.hs b/Control/Monad/Trans/Except.hs
--- a/Control/Monad/Trans/Except.hs
+++ b/Control/Monad/Trans/Except.hs
@@ -16,7 +16,8 @@
 -- Stability   :  experimental
 -- Portability :  portable
 --
--- This monad transformer extends a monad with the ability to throw exceptions.
+-- This monad transformer extends a monad with the ability to throw
+-- and catch exceptions.
 --
 -- A sequence of actions terminates normally, producing a value,
 -- only if none of the actions in the sequence throws an exception.
@@ -35,8 +36,7 @@
     mapExcept,
     withExcept,
     -- * The ExceptT monad transformer
-    ExceptT(ExceptT),
-    runExceptT,
+    ExceptT(..),
     mapExceptT,
     withExceptT,
     -- * Exception operations
@@ -45,6 +45,7 @@
     handleE,
     tryE,
     finallyE,
+    onE,
     -- * Lifting other operations
     liftCallCC,
     liftListen,
@@ -69,7 +70,7 @@
 #if MIN_VERSION_base(4,4,0)
 import Control.Monad.Zip (MonadZip(mzipWith))
 #endif
-#if !(MIN_VERSION_base(4,8,0))
+#if !(MIN_VERSION_base(4,8,0)) || defined(__MHS__)
 import Data.Foldable (Foldable(foldMap))
 import Data.Monoid (Monoid(mempty, mappend))
 import Data.Traversable (Traversable(traverse))
@@ -78,9 +79,11 @@
 import GHC.Generics
 #endif
 
--- | The parameterizable exception monad.
+-- | The parameterizable exception monad, which is strict.
 --
--- Computations are either exceptions or normal values.
+-- Computations are either exceptions (of any type) or normal values.
+-- These computations are plain values, and are unrelated to the
+-- "Control.Exception" mechanism, which is tied to the 'IO' monad.
 --
 -- The 'return' function returns a normal value, while @>>=@ exits on
 -- the first exception.  For a variant that continues after an error
@@ -116,16 +119,19 @@
 
 -- | A monad transformer that adds exceptions to other monads.
 --
--- @ExceptT@ constructs a monad parameterized over two things:
+-- @ExceptT@ constructs a strict monad parameterized over two things:
 --
--- * e - The exception type.
+-- * e - An arbitrary exception type.
 --
 -- * m - The inner monad.
 --
+-- The monadic computations are a plain values.  They are unrelated to
+-- the "Control.Exception" mechanism, which is tied to the 'IO' monad.
+--
 -- The 'return' function yields a computation that produces the given
 -- value, while @>>=@ sequences two subcomputations, exiting on the
 -- first exception.
-newtype ExceptT e m a = ExceptT (m (Either e a))
+newtype ExceptT e m a = ExceptT { runExceptT :: m (Either e a) }
 #if __GLASGOW_HASKELL__ >= 710
     deriving (Generic, Generic1)
 #elif __GLASGOW_HASKELL__ >= 704
@@ -164,11 +170,6 @@
 instance (Show e, Show1 m, Show a) => Show (ExceptT e m a) where
     showsPrec = showsPrec1
 
--- | The inverse of 'ExceptT'.
-runExceptT :: ExceptT e m a -> m (Either e a)
-runExceptT (ExceptT m) = m
-{-# INLINE runExceptT #-}
-
 -- | Map the unwrapped computation using the given function.
 --
 -- * @'runExceptT' ('mapExceptT' f m) = f ('runExceptT' m)@
@@ -328,6 +329,14 @@
     closer
     either throwE return res
 {-# INLINE finallyE #-}
+
+-- | If the first action succeeds, return its value, ignoring the
+-- second action.  If the first action throws an exception, run the
+-- second action and then throw an exception, either the one thrown by
+-- the second action, if any, or the one thrown by the first action.
+onE :: (Monad m) => ExceptT e m a -> ExceptT e m b -> ExceptT e m a
+onE action1 action2 = action1 `catchE` \ e -> action2 >> throwE e
+{-# INLINE onE #-}
 
 -- | Lift a @callCC@ operation to the new monad.
 liftCallCC :: CallCC m (Either e a) (Either e b) -> CallCC (ExceptT e m) a b
diff --git a/Control/Monad/Trans/Identity.hs b/Control/Monad/Trans/Identity.hs
--- a/Control/Monad/Trans/Identity.hs
+++ b/Control/Monad/Trans/Identity.hs
@@ -54,7 +54,7 @@
 import Control.Monad.Zip (MonadZip(mzipWith))
 #endif
 import Data.Foldable
-#if !(MIN_VERSION_base(4,8,0))
+#if !(MIN_VERSION_base(4,8,0)) || defined(__MHS__)
 import Data.Traversable (Traversable(traverse))
 #endif
 import Prelude hiding (foldr, foldr1, foldl, foldl1, null, length)
diff --git a/Control/Monad/Trans/Maybe.hs b/Control/Monad/Trans/Maybe.hs
--- a/Control/Monad/Trans/Maybe.hs
+++ b/Control/Monad/Trans/Maybe.hs
@@ -61,7 +61,7 @@
 import Control.Monad.Zip (MonadZip(mzipWith))
 #endif
 import Data.Maybe (fromMaybe)
-#if !(MIN_VERSION_base(4,8,0))
+#if !(MIN_VERSION_base(4,8,0)) || defined(__MHS__)
 import Data.Foldable (Foldable(foldMap))
 import Data.Traversable (Traversable(traverse))
 #endif
@@ -69,8 +69,8 @@
 import GHC.Generics
 #endif
 
--- | The parameterizable maybe monad, obtained by composing an arbitrary
--- monad with the 'Maybe' monad.
+-- | The parameterizable maybe monad, a strict monad obtained by composing
+-- an arbitrary monad with the 'Maybe' monad.
 --
 -- Computations are actions that may produce a value or exit.
 --
diff --git a/Control/Monad/Trans/RWS/CPS.hs b/Control/Monad/Trans/RWS/CPS.hs
--- a/Control/Monad/Trans/RWS/CPS.hs
+++ b/Control/Monad/Trans/RWS/CPS.hs
@@ -409,6 +409,9 @@
 {-# INLINE liftCallCC' #-}
 
 -- | Lift a @catchE@ operation to the new monad.
+-- The uniformity property (see "Control.Monad.Signatures") implies that
+-- the lifted @catchE@ discards any output or changes to the state from
+-- the body on entering the handler.
 liftCatch :: Catch e m (a,s,w) -> Catch e (RWST r w s m) a
 liftCatch catchE m h =
     RWST $ \ r s w -> unRWST m r s w `catchE` \ e -> unRWST (h e) r s w
diff --git a/Control/Monad/Trans/RWS/Lazy.hs b/Control/Monad/Trans/RWS/Lazy.hs
--- a/Control/Monad/Trans/RWS/Lazy.hs
+++ b/Control/Monad/Trans/RWS/Lazy.hs
@@ -393,6 +393,9 @@
 {-# INLINE liftCallCC' #-}
 
 -- | Lift a @catchE@ operation to the new monad.
+-- The uniformity property (see "Control.Monad.Signatures") implies that
+-- the lifted @catchE@ discards any output or changes to the state from
+-- the body on entering the handler.
 liftCatch :: Catch e m (a,s,w) -> Catch e (RWST r w s m) a
 liftCatch catchE m h =
     RWST $ \ r s -> runRWST m r s `catchE` \ e -> runRWST (h e) r s
diff --git a/Control/Monad/Trans/RWS/Strict.hs b/Control/Monad/Trans/RWS/Strict.hs
--- a/Control/Monad/Trans/RWS/Strict.hs
+++ b/Control/Monad/Trans/RWS/Strict.hs
@@ -397,6 +397,9 @@
 {-# INLINE liftCallCC' #-}
 
 -- | Lift a @catchE@ operation to the new monad.
+-- The uniformity property (see "Control.Monad.Signatures") implies that
+-- the lifted @catchE@ discards any output or changes to the state from
+-- the body on entering the handler.
 liftCatch :: Catch e m (a,s,w) -> Catch e (RWST r w s m) a
 liftCatch catchE m h =
     RWST $ \ r s -> runRWST m r s `catchE` \ e -> runRWST (h e) r s
diff --git a/Control/Monad/Trans/Reader.hs b/Control/Monad/Trans/Reader.hs
--- a/Control/Monad/Trans/Reader.hs
+++ b/Control/Monad/Trans/Reader.hs
@@ -71,12 +71,15 @@
 import GHC.Generics
 #endif
 
--- | The parameterizable reader monad.
+-- | The parameterizable reader monad, which is non-strict.
 --
 -- Computations are functions of a shared environment.
 --
--- The 'return' function ignores the environment, while @>>=@ passes
--- the inherited environment to both subcomputations.
+-- The 'return' function ignores the environment, while @m '>>=' k@
+-- passes the inherited environment to both subcomputations:
+--
+-- <<images/bind-ReaderT.svg>>
+--
 type Reader r = ReaderT r Identity
 
 -- | Constructor for computations in the reader monad (equivalent to 'asks').
@@ -114,8 +117,13 @@
 -- | The reader monad transformer,
 -- which adds a read-only environment to the given monad.
 --
--- The 'return' function ignores the environment, while @>>=@ passes
--- the inherited environment to both subcomputations.
+-- The 'return' function ignores the environment, while @m '>>=' k@
+-- passes the inherited environment to both subcomputations:
+--
+-- <<images/bind-ReaderT.svg>>
+--
+--
+-- @ReaderT r m@ is strict if and only if @m@ is.
 newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
 #if __GLASGOW_HASKELL__ >= 710
     deriving (Generic, Generic1)
diff --git a/Control/Monad/Trans/Select.hs b/Control/Monad/Trans/Select.hs
--- a/Control/Monad/Trans/Select.hs
+++ b/Control/Monad/Trans/Select.hs
@@ -37,8 +37,7 @@
     runSelect,
     mapSelect,
     -- * The SelectT monad transformer
-    SelectT(SelectT),
-    runSelectT,
+    SelectT(..),
     mapSelectT,
     -- * Monad transformation
     selectToContT,
@@ -58,7 +57,7 @@
 import GHC.Generics
 #endif
 
--- | Selection monad.
+-- | The selection monad, which is non-strict.
 type Select r = SelectT r Identity
 
 -- | Constructor for computations in the selection monad.
@@ -83,16 +82,15 @@
 --
 -- 'SelectT' is not a functor on the category of monads, and many operations
 -- cannot be lifted through it.
-newtype SelectT r m a = SelectT ((a -> m r) -> m a)
+--
+-- @SelectT r m@ is strict if and only if @m@ is.
+newtype SelectT r m a = SelectT {
+    -- | Runs a @SelectT@ computation with a function for evaluating
+    -- answers to select a particular answer.
+    runSelectT :: (a -> m r) -> m a }
 #if __GLASGOW_HASKELL__ >= 704
     deriving (Generic)
 #endif
-
--- | Runs a @SelectT@ computation with a function for evaluating answers
--- to select a particular answer.  (The inverse of 'select'.)
-runSelectT :: SelectT r m a -> (a -> m r) -> m a
-runSelectT (SelectT g) = g
-{-# INLINE runSelectT #-}
 
 -- | Apply a function to transform the result of a selection computation.
 -- This has a more restricted type than the @map@ operations for other
diff --git a/Control/Monad/Trans/State/Lazy.hs b/Control/Monad/Trans/State/Lazy.hs
--- a/Control/Monad/Trans/State/Lazy.hs
+++ b/Control/Monad/Trans/State/Lazy.hs
@@ -64,6 +64,9 @@
     liftCatch,
     liftListen,
     liftPass,
+    -- * Conversion to and from the strict version
+    strictToLazyStateT,
+    lazyToStrictStateT,
     -- * Examples
     -- ** State monads
     -- $examples
@@ -78,6 +81,7 @@
 import Control.Monad.IO.Class
 import Control.Monad.Signatures
 import Control.Monad.Trans.Class
+import qualified Control.Monad.Trans.State.Strict as Strict
 #if MIN_VERSION_base(4,12,0)
 import Data.Functor.Contravariant
 #endif
@@ -336,6 +340,9 @@
 {-# INLINE liftCallCC' #-}
 
 -- | Lift a @catchE@ operation to the new monad.
+-- The uniformity property (see "Control.Monad.Signatures") implies
+-- that the lifted @catchE@ rolls back to the original state on entering
+-- the handler.
 liftCatch :: Catch e m (a,s) -> Catch e (StateT s m) a
 liftCatch catchE m h =
     StateT $ \ s -> runStateT m s `catchE` \ e -> runStateT (h e) s
@@ -354,6 +361,16 @@
     ~((a, f), s') <- runStateT m s
     return ((a, s'), f)
 {-# INLINE liftPass #-}
+
+-- | Convert from the strict version to the lazy version
+strictToLazyStateT :: Strict.StateT s m a -> StateT s m a
+strictToLazyStateT (Strict.StateT f) = StateT f
+{-# INLINE strictToLazyStateT #-}
+
+-- | Convert from the lazy version to the strict version
+lazyToStrictStateT :: StateT s m a -> Strict.StateT s m a
+lazyToStrictStateT (StateT f) = Strict.StateT f
+{-# INLINE lazyToStrictStateT #-}
 
 {- $examples
 
diff --git a/Control/Monad/Trans/State/Strict.hs b/Control/Monad/Trans/State/Strict.hs
--- a/Control/Monad/Trans/State/Strict.hs
+++ b/Control/Monad/Trans/State/Strict.hs
@@ -337,6 +337,9 @@
 {-# INLINE liftCallCC' #-}
 
 -- | Lift a @catchE@ operation to the new monad.
+-- The uniformity property (see "Control.Monad.Signatures") implies
+-- that the lifted @catchE@ rolls back to the original state on entering
+-- the handler.
 liftCatch :: Catch e m (a,s) -> Catch e (StateT s m) a
 liftCatch catchE m h =
     StateT $ \ s -> runStateT m s `catchE` \ e -> runStateT (h e) s
diff --git a/Control/Monad/Trans/Writer/CPS.hs b/Control/Monad/Trans/Writer/CPS.hs
--- a/Control/Monad/Trans/Writer/CPS.hs
+++ b/Control/Monad/Trans/Writer/CPS.hs
@@ -76,8 +76,12 @@
 -- ---------------------------------------------------------------------------
 -- | A writer monad parameterized by the type @w@ of output to accumulate.
 --
--- The 'return' function produces the output 'mempty', while '>>='
--- combines the outputs of the subcomputations using 'mappend'.
+-- The 'return' function produces the output 'mempty', while @m '>>=' k@
+-- combines the outputs of the subcomputations using 'mappend' (also
+-- known as @<>@):
+--
+-- <<images/bind-WriterT.svg>>
+--
 type Writer w = WriterT w Identity
 
 -- | Construct a writer computation from a (result, output) pair.
@@ -116,9 +120,12 @@
 --
 --   * @m@ - The inner monad.
 --
--- The 'return' function produces the output 'mempty', while '>>='
--- combines the outputs of the subcomputations using 'mappend'.
-
+-- The 'return' function produces the output 'mempty', while @m '>>=' k@
+-- combines the outputs of the subcomputations using 'mappend' (also
+-- known as @<>@):
+--
+-- <<images/bind-WriterT.svg>>
+--
 newtype WriterT w m a = WriterT { unWriterT :: w -> m (a, w) }
 #if __GLASGOW_HASKELL__ >= 704
     deriving (Generic)
@@ -276,14 +283,18 @@
 {-# INLINE censor #-}
 
 -- | Uniform lifting of a @callCC@ operation to the new monad.
--- This version rolls back to the original state on entering the
--- continuation.
+-- The uniformity property (see "Control.Monad.Signatures") implies that
+-- the lifted @callCC@ discards any output from the body on entering
+-- the saved continuation.
 liftCallCC :: CallCC m (a, w) (b, w) -> CallCC (WriterT w m) a b
 liftCallCC callCC f = WriterT $ \ w ->
     callCC $ \ c -> unWriterT (f (\ a -> WriterT $ \ _ -> c (a, w))) w
 {-# INLINE liftCallCC #-}
 
 -- | Lift a @catchE@ operation to the new monad.
+-- The uniformity property (see "Control.Monad.Signatures") implies that
+-- the lifted @catchE@ discards any output from the body on entering
+-- the handler.
 liftCatch :: Catch e m (a, w) -> Catch e (WriterT w m) a
 liftCatch catchE m h = WriterT $ \ w ->
     unWriterT m w `catchE` \ e -> unWriterT (h e) w
diff --git a/Control/Monad/Trans/Writer/Lazy.hs b/Control/Monad/Trans/Writer/Lazy.hs
--- a/Control/Monad/Trans/Writer/Lazy.hs
+++ b/Control/Monad/Trans/Writer/Lazy.hs
@@ -70,7 +70,7 @@
 #endif
 import Data.Foldable
 import Data.Monoid
-#if !(MIN_VERSION_base(4,8,0))
+#if !(MIN_VERSION_base(4,8,0)) || defined(__MHS__)
 import Data.Traversable (Traversable(traverse))
 #endif
 import Prelude hiding (null, length)
@@ -81,8 +81,12 @@
 -- ---------------------------------------------------------------------------
 -- | A writer monad parameterized by the type @w@ of output to accumulate.
 --
--- The 'return' function produces the output 'mempty', while @>>=@
--- combines the outputs of the subcomputations using 'mappend'.
+-- The 'return' function produces the output 'mempty', while @m '>>=' k@
+-- combines the outputs of the subcomputations using 'mappend' (also
+-- known as @<>@):
+--
+-- <<images/bind-WriterT.svg>>
+--
 type Writer w = WriterT w Identity
 
 -- | Construct a writer computation from a (result, output) pair.
@@ -119,8 +123,12 @@
 --
 --   * @m@ - The inner monad.
 --
--- The 'return' function produces the output 'mempty', while @>>=@
--- combines the outputs of the subcomputations using 'mappend'.
+-- The 'return' function produces the output 'mempty', while @m '>>=' k@
+-- combines the outputs of the subcomputations using 'mappend' (also
+-- known as @<>@):
+--
+-- <<images/bind-WriterT.svg>>
+--
 newtype WriterT w m a = WriterT { runWriterT :: m (a, w) }
 #if __GLASGOW_HASKELL__ >= 704
     deriving (Generic)
@@ -309,6 +317,9 @@
 {-# INLINE censor #-}
 
 -- | Lift a @callCC@ operation to the new monad.
+-- The uniformity property (see "Control.Monad.Signatures") implies that
+-- the lifted @callCC@ discards any output from the body on entering
+-- the saved condinuation.
 liftCallCC :: (Monoid w) => CallCC m (a,w) (b,w) -> CallCC (WriterT w m) a b
 liftCallCC callCC f = WriterT $
     callCC $ \ c ->
@@ -316,6 +327,9 @@
 {-# INLINE liftCallCC #-}
 
 -- | Lift a @catchE@ operation to the new monad.
+-- The uniformity property (see "Control.Monad.Signatures") implies that
+-- the lifted @catchE@ discards any output from the body on entering
+-- the handler.
 liftCatch :: Catch e m (a,w) -> Catch e (WriterT w m) a
 liftCatch catchE m h =
     WriterT $ runWriterT m `catchE` \ e -> runWriterT (h e)
diff --git a/Control/Monad/Trans/Writer/Strict.hs b/Control/Monad/Trans/Writer/Strict.hs
--- a/Control/Monad/Trans/Writer/Strict.hs
+++ b/Control/Monad/Trans/Writer/Strict.hs
@@ -73,7 +73,7 @@
 #endif
 import Data.Foldable
 import Data.Monoid
-#if !(MIN_VERSION_base(4,8,0))
+#if !(MIN_VERSION_base(4,8,0)) || defined(__MHS__)
 import Data.Traversable (Traversable(traverse))
 #endif
 import Prelude hiding (null, length)
@@ -84,8 +84,12 @@
 -- ---------------------------------------------------------------------------
 -- | A writer monad parameterized by the type @w@ of output to accumulate.
 --
--- The 'return' function produces the output 'mempty', while @>>=@
--- combines the outputs of the subcomputations using 'mappend'.
+-- The 'return' function produces the output 'mempty', while @m '>>=' k@
+-- combines the outputs of the subcomputations using 'mappend' (also
+-- known as @<>@):
+--
+-- <<images/bind-WriterT.svg>>
+--
 type Writer w = WriterT w Identity
 
 -- | Construct a writer computation from a (result, output) pair.
@@ -122,8 +126,12 @@
 --
 --   * @m@ - The inner monad.
 --
--- The 'return' function produces the output 'mempty', while @>>=@
--- combines the outputs of the subcomputations using 'mappend'.
+-- The 'return' function produces the output 'mempty', while @m '>>=' k@
+-- combines the outputs of the subcomputations using 'mappend' (also
+-- known as @<>@):
+--
+-- <<images/bind-WriterT.svg>>
+--
 newtype WriterT w m a = WriterT { runWriterT :: m (a, w) }
 #if __GLASGOW_HASKELL__ >= 704
     deriving (Generic)
@@ -312,6 +320,9 @@
 {-# INLINE censor #-}
 
 -- | Lift a @callCC@ operation to the new monad.
+-- The uniformity property (see "Control.Monad.Signatures") implies that
+-- the lifted @callCC@ discards any output from the body on entering
+-- the saved continuation.
 liftCallCC :: (Monoid w) => CallCC m (a,w) (b,w) -> CallCC (WriterT w m) a b
 liftCallCC callCC f = WriterT $
     callCC $ \ c ->
@@ -319,6 +330,9 @@
 {-# INLINE liftCallCC #-}
 
 -- | Lift a @catchE@ operation to the new monad.
+-- The uniformity property (see "Control.Monad.Signatures") implies that
+-- the lifted @catchE@ discards any output from the body on entering
+-- the handler.
 liftCatch :: Catch e m (a,w) -> Catch e (WriterT w m) a
 liftCatch catchE m h =
     WriterT $ runWriterT m `catchE` \ e -> runWriterT (h e)
diff --git a/Data/Functor/Constant.hs b/Data/Functor/Constant.hs
--- a/Data/Functor/Constant.hs
+++ b/Data/Functor/Constant.hs
@@ -36,7 +36,7 @@
 
 import Control.Applicative
 import Data.Foldable
-#if !(MIN_VERSION_base(4,8,0))
+#if !(MIN_VERSION_base(4,8,0)) || defined(__MHS__)
 import Data.Monoid (Monoid(..))
 import Data.Traversable (Traversable(traverse))
 #endif
diff --git a/Data/Functor/Reverse.hs b/Data/Functor/Reverse.hs
--- a/Data/Functor/Reverse.hs
+++ b/Data/Functor/Reverse.hs
@@ -43,7 +43,7 @@
 import qualified Control.Monad.Fail as Fail
 #endif
 import Data.Foldable
-#if !(MIN_VERSION_base(4,8,0))
+#if !(MIN_VERSION_base(4,8,0)) || defined(__MHS__)
 import Data.Traversable (Traversable(traverse))
 #endif
 import Data.Monoid
diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,5 +1,21 @@
 -*-change-log-*-
 
+0.6.3.0 Ross Paterson <R.Paterson@city.ac.uk> Jan 2026
+	* Add Control.Monad.Trans.Except.onE
+	* Add strictToLazyState and lazyToStrictStateT
+
+0.6.2.0 Ross Paterson <R.Paterson@city.ac.uk> Apr 2025
+	* Redefine runAccumT, runExceptT and runSelectT as fields
+	* Document strictness of some transformers
+
+0.6.1.2 Ross Paterson <R.Paterson@city.ac.uk> Sep 2024
+	* Portability fixes for MicroHs
+	* Include image files in the bundle
+	* Expand ExceptT documentation
+
+0.6.1.1 Ross Paterson <R.Paterson@city.ac.uk> Aug 2023
+	* Additions to documentation, especially of AccumT.
+
 0.6.1.0 Ross Paterson <R.Paterson@city.ac.uk> Feb 2023
 	* Add instances of Foldable1 (class added to base-4.18)
 	* Add modifyM to StateT transformers
diff --git a/images/bind-AccumT.svg b/images/bind-AccumT.svg
new file mode 100644
--- /dev/null
+++ b/images/bind-AccumT.svg
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="390" height="180"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<defs>
+  <marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5"
+        markerWidth="5" markerHeight="5"
+        orient="auto-start-reverse">
+      <path d="M 0 0 L 10 5 L 0 10 z" />
+  </marker>
+  <marker id="extra-arrow" viewBox="0 0 10 10" refX="5" refY="5"
+        markerWidth="5" markerHeight="5"
+        orient="auto-start-reverse">
+      <path fill="#44f" d="M 0 0 L 10 5 L 0 10 z" />
+  </marker>
+  <style type="text/css">
+    line.arrow {
+        fill: none; stroke: black; stroke-width: 4;
+        marker-end: url(#arrow);
+    }
+    circle.action {
+        fill: #f8ddbb; stroke: black; stroke-width: 4;
+    }
+    text.action {
+        fill: black; stroke: none;
+        font-family: sans-serif; font-size: 35px;
+        dominant-baseline: central; text-anchor: middle;
+    }
+    .extra {
+        fill: none; stroke: #44f; stroke-width: 3;
+        marker-end: url(#extra-arrow);
+    }
+    circle.mappend {
+        fill: none; stroke: #44f; stroke-width: 3;
+    }
+    text.mappend {
+        fill: #44f; stroke: none;
+        font-family: sans-serif; font-size: 26px;
+        dominant-baseline: central; text-anchor: middle;
+    }
+  </style>
+</defs>
+<g transform="scale(0.6) translate(50,50)">
+  <path class="extra" d="M 0,0 L 80,0 A 20 20 0 0 1 100,20 L 100,52"/>
+  <path class="extra" d="M 80,0 L 225,0"/>
+  <circle class="mappend" cx="250" cy="0" r="20"/>
+  <text class="mappend" x="250" y="0">&lt;&gt;</text>
+  <path class="extra" d="M 270,0 L 380,0 A 20 20 0 0 1 400,20 L 400,52"/>
+  <path class="extra" d="M 230,200 A 20 20 0 0 0 250,180 L 250,27"/>
+  <path class="extra" d="M 100,140 L 100,180 A 20 20 0 0 0 120,200 L 373,200"/>
+  <circle class="mappend" cx="400" cy="200" r="20"/>
+  <text class="mappend" x="400" y="200">&lt;&gt;</text>
+  <path class="extra" d="M 400,140 L 400,173"/>
+  <path class="extra" d="M 420,200 L 550,200"/>
+  <text class="mappend" x="15" y="-20">w</text>
+
+  <line class="arrow" x1="140" y1="100" x2="350" y2="100"/>
+  <line class="arrow" x1="440" y1="100" x2="550" y2="100"/>
+  <circle class="action" cx="100" cy="100" r="40"/>
+  <text class="action" x="100" y="100">m</text>
+  <circle class="action" cx="400" cy="100" r="40"/>
+  <text class="action" x="400" y="100">k</text>
+</g>
+</svg>
diff --git a/images/bind-ReaderT.svg b/images/bind-ReaderT.svg
new file mode 100644
--- /dev/null
+++ b/images/bind-ReaderT.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="390" height="150"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<defs>
+  <marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5"
+        markerWidth="5" markerHeight="5"
+        orient="auto-start-reverse">
+      <path d="M 0 0 L 10 5 L 0 10 z" />
+  </marker>
+  <marker id="extra-arrow" viewBox="0 0 10 10" refX="5" refY="5"
+        markerWidth="5" markerHeight="5"
+        orient="auto-start-reverse">
+      <path fill="#44f" d="M 0 0 L 10 5 L 0 10 z" />
+  </marker>
+  <style type="text/css">
+    line.arrow {
+        fill: none; stroke: black; stroke-width: 4;
+        marker-end: url(#arrow);
+    }
+    circle.action {
+        fill: #f8ddbb; stroke: black; stroke-width: 4;
+    }
+    text.action {
+        fill: black; stroke: none;
+        font-family: sans-serif; font-size: 35px;
+        dominant-baseline: central; text-anchor: middle;
+    }
+    .extra {
+        fill: none; stroke: #44f; stroke-width: 3;
+        marker-end: url(#extra-arrow);
+    }
+    circle.mappend {
+        fill: none; stroke: #44f; stroke-width: 3;
+    }
+    text.mappend {
+        fill: #44f; stroke: none;
+        font-family: sans-serif; font-size: 26px;
+        dominant-baseline: central; text-anchor: middle;
+    }
+  </style>
+</defs>
+<g transform="scale(0.6) translate(50,50)">
+  <path class="extra" d="M 0,0 L 80,0 A 20 20 0 0 1 100,20 L 100,52"/>
+  <path class="extra" d="M 80,0 L 380,0 A 20 20 0 0 1 400,20 L 400,52"/>
+  <text class="mappend" x="15" y="-20">r</text>
+
+  <line class="arrow" x1="140" y1="100" x2="350" y2="100"/>
+  <line class="arrow" x1="440" y1="100" x2="550" y2="100"/>
+  <circle class="action" cx="100" cy="100" r="40"/>
+  <text class="action" x="100" y="100">m</text>
+  <circle class="action" cx="400" cy="100" r="40"/>
+  <text class="action" x="400" y="100">k</text>
+</g>
+</svg>
diff --git a/images/bind-WriterT.svg b/images/bind-WriterT.svg
new file mode 100644
--- /dev/null
+++ b/images/bind-WriterT.svg
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="360" height="150"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<defs>
+  <marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5"
+        markerWidth="5" markerHeight="5"
+        orient="auto-start-reverse">
+      <path d="M 0 0 L 10 5 L 0 10 z" />
+  </marker>
+  <marker id="extra-arrow" viewBox="0 0 10 10" refX="5" refY="5"
+        markerWidth="5" markerHeight="5"
+        orient="auto-start-reverse">
+      <path fill="#44f" d="M 0 0 L 10 5 L 0 10 z" />
+  </marker>
+  <style type="text/css">
+    line.arrow {
+        fill: none; stroke: black; stroke-width: 4;
+        marker-end: url(#arrow);
+    }
+    circle.action {
+        fill: #f8ddbb; stroke: black; stroke-width: 4;
+    }
+    text.action {
+        fill: black; stroke: none;
+        font-family: sans-serif; font-size: 35px;
+        dominant-baseline: central; text-anchor: middle;
+    }
+    .extra {
+        fill: none; stroke: #44f; stroke-width: 3;
+        marker-end: url(#extra-arrow);
+    }
+    circle.mappend {
+        fill: none; stroke: #44f; stroke-width: 3;
+    }
+    text.mappend {
+        fill: #44f; stroke: none;
+        font-family: sans-serif; font-size: 26px;
+        dominant-baseline: central; text-anchor: middle;
+    }
+  </style>
+</defs>
+<g transform="scale(0.6)">
+  <path class="extra" d="M 100,140 L 100,180 A 20 20 0 0 0 120,200 L 373,200"/>
+  <circle class="mappend" cx="400" cy="200" r="20"/>
+  <text class="mappend" x="400" y="200">&lt;&gt;</text>
+  <path class="extra" d="M 400,140 L 400,173"/>
+  <path class="extra" d="M 420,200 L 550,200"/>
+  <text class="mappend" x="520" y="180">w</text>
+
+  <line class="arrow" x1="140" y1="100" x2="350" y2="100"/>
+  <line class="arrow" x1="440" y1="100" x2="550" y2="100"/>
+  <circle class="action" cx="100" cy="100" r="40"/>
+  <text class="action" x="100" y="100">m</text>
+  <circle class="action" cx="400" cy="100" r="40"/>
+  <text class="action" x="400" y="100">k</text>
+</g>
+</svg>
diff --git a/transformers.cabal b/transformers.cabal
--- a/transformers.cabal
+++ b/transformers.cabal
@@ -1,5 +1,5 @@
 name:         transformers
-version:      0.6.1.0
+version:      0.6.3.0
 license:      BSD3
 license-file: LICENSE
 author:       Andy Gill, Ross Paterson
@@ -31,9 +31,12 @@
     the @mtl@ or @monads-tf@ packages, which automatically lift operations
     introduced by monad transformers through other transformers.
 build-type: Simple
-extra-source-files:
+extra-doc-files:
     changelog
-cabal-version: >= 1.10
+    images/bind-AccumT.svg
+    images/bind-ReaderT.svg
+    images/bind-WriterT.svg
+cabal-version: 1.18
 
 source-repository head
   type: darcs
@@ -43,13 +46,13 @@
   default-language: Haskell2010
   build-depends: base >= 2 && < 6
   hs-source-dirs: .
-  if !impl(ghc>=7.9)
+  if impl(ghc<7.9)
     -- Data.Functor.Identity was moved into base-4.8.0.0 (GHC 7.10)
     -- see also https://ghc.haskell.org/trac/ghc/ticket/9664
     -- NB: using impl(ghc>=7.9) instead of fragile Cabal flags
     hs-source-dirs: legacy/pre709
     exposed-modules: Data.Functor.Identity
-  if !impl(ghc>=7.11)
+  if impl(ghc<7.11)
     -- modules moved into base-4.9.0 (GHC 8.0)
     -- see https://ghc.haskell.org/trac/ghc/ticket/10773
     -- see https://ghc.haskell.org/trac/ghc/ticket/11135
@@ -62,7 +65,7 @@
       Data.Functor.Sum
   if impl(ghc>=7.2 && <7.5)
     -- Prior to GHC 7.5, GHC.Generics lived in ghc-prim
-    build-depends: ghc-prim
+    build-depends: ghc-prim < 0.3
   exposed-modules:
     Control.Applicative.Backwards
     Control.Applicative.Lift
