diff --git a/CHANGES b/CHANGES
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,10 @@
+Version 3.0
+  * Add instane from `MonadFail`---none of the transformers implement this
+    functionality so the implementation just lifts things.
+
+Version 3.8
+  * Added `WithBase`
+
 Version 3.3.0
 
 * Remove 'RunStateM'
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,6 @@
-Copyright (c) 2006 Iavor S. Diatchki
+Copyright 2006 Iavor S. Diatchki
 
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
 
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/monadLib.cabal b/monadLib.cabal
--- a/monadLib.cabal
+++ b/monadLib.cabal
@@ -1,43 +1,30 @@
+cabal-version:  3.0
 Name:           monadLib
-Version:        3.7.3
-License:        BSD3
+Version:        3.10.3
+License:        ISC
 License-file:   LICENSE
 Author:         Iavor S. Diatchki
 Maintainer:     diatchki@galois.com
-Homepage:       http://wiki.github.com/yav/monadlib
+Homepage:       https://github.com/yav/monadlib
 Category:       Monads
 Synopsis:       A collection of monad transformers.
 Description:    A collection of monad transformers.
 Build-type:     Simple
-Cabal-version: >= 1.2
 Extra-source-files:
   LICENSE,
   README,
   CHANGES
 
-Flag base3
-  Description: Build for compatability with base3
-  Default:     False
 
 Library
+  default-language: Haskell2010
   hs-source-dirs: src
   Exposed-modules:
     MonadLib,
     MonadLib.Monads,
     MonadLib.Derive
-  Extensions:
-    CPP,
-    MultiParamTypeClasses,
-    FunctionalDependencies,
-    Rank2Types,
-    FlexibleInstances,
-    UndecidableInstances
 
-  if flag(base3)
-    Build-depends: base < 4
-    CPP-options: -DUSE_BASE3
-  else
-    Build-depends: base >= 4 && < 5
+  Build-depends: base >= 4.9 && < 5
 
   GHC-options:    -O2 -Wall
 
diff --git a/src/MonadLib.hs b/src/MonadLib.hs
--- a/src/MonadLib.hs
+++ b/src/MonadLib.hs
@@ -1,8 +1,9 @@
 {-# LANGUAGE CPP, MultiParamTypeClasses, FunctionalDependencies,
-             UndecidableInstances, FlexibleInstances #-}
+             UndecidableInstances, FlexibleInstances, FlexibleContexts #-}
+{-# LANGUAGE DataKinds, TypeFamilies, TypeOperators #-}
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE Trustworthy #-}
+{-# LANGUAGE Safe #-}
 {-| This library provides a collection of monad transformers that
     can be combined to produce various monads.
 -}
@@ -43,30 +44,20 @@
   asks, puts, sets, sets_, raises,
   mapReader, mapWriter, mapException,
   handle,
+  WithBase,
 
-  -- * Miscellaneous
-  version,
   module Control.Monad
 ) where
 
-
 import Control.Applicative
 import Control.Monad
 import Control.Monad.Fix
 import Control.Monad.ST (ST)
-import qualified Control.Exception as IO (throwIO,try)
-#ifdef USE_BASE3
-import qualified Control.Exception as IO (Exception)
-#else
-import qualified Control.Exception as IO (SomeException)
-#endif
+import qualified Control.Exception as IO (throwIO,try,SomeException)
 import System.Exit(ExitCode,exitWith)
-import Data.Monoid
+import Data.Kind(Type)
 import Prelude hiding (Ordering(..))
-
--- | The current version of the library.
-version :: (Int,Int,Int)
-version = (3,5,2)
+import qualified Control.Monad.Fail as MF
 
 
 -- $Types
@@ -258,9 +249,14 @@
 t_return   :: (MonadT t, Monad m) => a -> t m a
 t_return x  = lift (return x)
 
-t_fail     :: (MonadT t, Monad m) => String -> t m a
-t_fail x    = lift (fail x)
+t_fail     :: (MonadT t, MF.MonadFail m) => String -> t m a
+t_fail x    = lift (MF.fail x)
 
+#if !MIN_VERSION_base(4,11,0)
+t_oldfail  :: (MonadT t, Monad m) => String -> t m a
+t_oldfail x = lift (fail x)
+#endif
+
 t_mzero    :: (MonadT t, MonadPlus m) => t m a
 t_mzero     = lift mzero
 
@@ -307,64 +303,82 @@
 
 
 instance Monad Id where
-  return x = I x
-  fail x   = error x
   m >>= k  = k (runId m)
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = error
+#endif
+
 instance Monad Lift where
-  return x  = L x
-  fail x    = error x
   L x >>= k = k x     -- Note: the pattern is important here
                       -- because it makes things strict
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = error
+#endif
 
+
 -- Note: None of the transformers make essential use of the 'fail' method.
 -- Instead, they delegate its behavior to the underlying monad.
 
 instance (Monad m) => Monad (IdT m) where
-  return  = t_return
-  fail    = t_fail
   m >>= k = IT (runIdT m >>= (runIdT . k))
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = t_oldfail
+#endif
+
 instance (Monad m) => Monad (ReaderT i m) where
-  return  = t_return
-  fail    = t_fail
   m >>= k = R (\r -> runReaderT r m >>= \a -> runReaderT r (k a))
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = t_oldfail
+#endif
+
 instance (Monad m) => Monad (StateT i m) where
-  return  = t_return
-  fail    = t_fail
   m >>= k = S (\s -> runStateT s m >>= \ ~(a,s') -> runStateT s' (k a))
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = t_oldfail
+#endif
+
 instance (Monad m,Monoid i) => Monad (WriterT i m) where
-  return  = t_return
-  fail    = t_fail
   m >>= k = W $ unW m     >>= \ ~(P a w1) ->
                 unW (k a) >>= \ ~(P b w2) ->
                 return (P b (mappend w1 w2))
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = t_oldfail
+#endif
+
 instance (Monad m) => Monad (ExceptionT i m) where
-  return  = t_return
-  fail    = t_fail
   m >>= k = X $ runExceptionT m >>= \e ->
                 case e of
                   Left x  -> return (Left x)
                   Right a -> runExceptionT (k a)
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = t_oldfail
+#endif
+
 instance (Monad m) => Monad (ChoiceT m) where
-  return x  = Answer x
-  fail x    = lift (fail x)
 
   Answer a  >>= k     = k a
   NoAnswer >>= _      = NoAnswer
   Choice m1 m2 >>= k  = Choice (m1 >>= k) (m2 >>= k)
   ChoiceEff m >>= k   = ChoiceEff (liftM (>>= k) m)
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = t_oldfail
+#endif
+
 instance (Monad m) => Monad (ContT i m) where
-  return  = t_return
-  fail    = t_fail
   m >>= k = C $ \c -> runContT (\a -> runContT c (k a)) m
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = t_oldfail
+#endif
+
 instance                       Functor Id               where fmap = liftM
 instance                       Functor Lift             where fmap = liftM
 instance (Monad m)          => Functor (IdT          m) where fmap = liftM
@@ -380,17 +394,17 @@
 -- NOTE: It may be possible to make these more general
 -- (i.e., have Applicative, or even Functor transformers)
 
-instance              Applicative Id            where (<*>) = ap; pure = return
-instance              Applicative Lift          where (<*>) = ap; pure = return
-instance (Monad m) => Applicative (IdT m)       where (<*>) = ap; pure = return
-instance (Monad m) => Applicative (ReaderT i m) where (<*>) = ap; pure = return
-instance (Monad m) => Applicative (StateT i m)  where (<*>) = ap; pure = return
+instance              Applicative Id            where (<*>) = ap; pure x = I x
+instance              Applicative Lift          where (<*>) = ap; pure x = L x
+instance (Monad m) => Applicative (IdT m)       where (<*>) = ap; pure = t_return
+instance (Monad m) => Applicative (ReaderT i m) where (<*>) = ap; pure = t_return
+instance (Monad m) => Applicative (StateT i m)  where (<*>) = ap; pure = t_return
 instance (Monad m,Monoid i)
-                   => Applicative (WriterT i m) where (<*>) = ap; pure = return
+                   => Applicative (WriterT i m) where (<*>) = ap; pure = t_return
 instance (Monad m) => Applicative (ExceptionT i m)
-                                                where (<*>) = ap; pure = return
-instance (Monad m) => Applicative (ChoiceT m)   where (<*>) = ap; pure = return
-instance (Monad m) => Applicative (ContT i m)   where (<*>) = ap; pure = return
+                                                where (<*>) = ap; pure = t_return
+instance (Monad m) => Applicative (ChoiceT m)   where (<*>) = ap; pure = Answer
+instance (Monad m) => Applicative (ContT i m)   where (<*>) = ap; pure = t_return
 
 instance (MonadPlus m)
            => Alternative (IdT m)           where (<|>) = mplus; empty = mzero
@@ -683,13 +697,8 @@
   -- successful computations are tagged with "Right".
   try :: m a -> m (Either i a)
 
-#ifdef USE_BASE3
-instance RunExceptionM IO IO.Exception where
-  try = IO.try
-#else
 instance RunExceptionM IO IO.SomeException where
   try = IO.try
-#endif
 
 instance (Monad m) => RunExceptionM (ExceptionT i m) i where
   try m = lift (runExceptionT m)
@@ -824,3 +833,38 @@
                          Left x  -> f x
 
 
+{- | A convenience type family for defining stacks of monads.
+The first entry in the list is the top-most layer of the monad stack
+(i.e., the one that is furtherest from the base).  For example:
+
+> newtype M a = M { unM ::
+>   WithBase IO
+>     '[ ReaderT    Int
+>      , StateT     Char
+>      , ExceptionT String
+>      ] a
+>   }
+
+is equivalent to:
+
+> newtype M a = M { unM ::
+>   ReaderT    Int      (
+>   StateT     Char     (
+>   ExceptionT String
+>   IO                  )) a
+>   }
+
+-}
+type family WithBase base layers :: Type -> Type where
+  WithBase b '[]        = b
+  WithBase b (f ': fs)  = f (WithBase b fs)
+
+
+instance MF.MonadFail m => MF.MonadFail (IdT          m) where fail = t_fail
+instance MF.MonadFail m => MF.MonadFail (ReaderT    i m) where fail = t_fail
+instance (Monoid i, MF.MonadFail m)
+                        => MF.MonadFail (WriterT    i m) where fail = t_fail
+instance MF.MonadFail m => MF.MonadFail (StateT     i m) where fail = t_fail
+instance MF.MonadFail m => MF.MonadFail (ExceptionT i m) where fail = t_fail
+instance MF.MonadFail m => MF.MonadFail (ChoiceT      m) where fail = t_fail
+instance MF.MonadFail m => MF.MonadFail (ContT      i m) where fail = t_fail
diff --git a/src/MonadLib/Derive.hs b/src/MonadLib/Derive.hs
--- a/src/MonadLib/Derive.hs
+++ b/src/MonadLib/Derive.hs
@@ -32,6 +32,7 @@
 import Control.Applicative
 import Control.Monad.Fix
 import Prelude hiding (Ordering(..))
+import Control.Monad.Fail as MF
 
 -- | An isomorphism between (usually) monads.
 -- Typically the constructor and selector of a newtype delcaration.
@@ -66,8 +67,8 @@
 derive_bind :: (Monad m) => Iso m n -> n a -> (a -> n b) -> n b
 derive_bind iso m k = close iso ((open iso m) >>= \x -> open iso (k x))
 
-derive_fail :: (Monad m) => Iso m n -> String -> n a
-derive_fail iso a = close iso (fail a)
+derive_fail :: (MF.MonadFail m) => Iso m n -> String -> n a
+derive_fail iso a = close iso (MF.fail a)
 
 -- | Derive the implementation of 'mfix' from 'MonadFix'.
 derive_mfix :: (MonadFix m) => Iso m n -> (a -> n a) -> n a
diff --git a/src/MonadLib/Monads.hs b/src/MonadLib/Monads.hs
--- a/src/MonadLib/Monads.hs
+++ b/src/MonadLib/Monads.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE Safe #-}
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-|  This module contains a collection of monads that
@@ -15,9 +16,7 @@
 ) where
 import MonadLib
 import MonadLib.Derive
-import Control.Applicative
 import Control.Monad.Fix
-import Data.Monoid
 
 newtype Reader    i a = R' { unR :: ReaderT    i Id a }
 newtype Writer    i a = W' { unW :: WriterT    i Id a }
@@ -44,41 +43,66 @@
 instance               BaseM (Cont      i) (Cont      i) where inBase = id
 
 instance Monad (Reader i) where
-  return  = derive_return iso_R
-  fail    = derive_fail iso_R
   (>>=)   = derive_bind iso_R
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = error
+#endif
+
 instance (Monoid i) => Monad (Writer i) where
-  return  = derive_return iso_W
-  fail    = derive_fail iso_W
   (>>=)   = derive_bind iso_W
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = error
+#endif
+
 instance Monad (State i) where
-  return  = derive_return iso_S
-  fail    = derive_fail iso_S
   (>>=)   = derive_bind iso_S
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = error
+#endif
+
+
 instance Monad (Exception i) where
-  return  = derive_return iso_X
-  fail    = derive_fail iso_X
   (>>=)   = derive_bind iso_X
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = error
+#endif
+
 instance Monad (Cont i) where
-  return  = derive_return iso_C
-  fail    = derive_fail iso_C
   (>>=)   = derive_bind iso_C
 
+#if !MIN_VERSION_base(4,11,0)
+  fail = error
+#endif
+
 instance               Functor (Reader    i) where fmap = derive_fmap iso_R
 instance (Monoid i) => Functor (Writer    i) where fmap = derive_fmap iso_W
 instance               Functor (State     i) where fmap = derive_fmap iso_S
 instance               Functor (Exception i) where fmap = derive_fmap iso_X
 instance               Functor (Cont      i) where fmap = derive_fmap iso_C
 
-instance               Applicative (Reader    i) where pure = return; (<*>) = ap
-instance (Monoid i) => Applicative (Writer    i) where pure = return; (<*>) = ap
-instance               Applicative (State     i) where pure = return; (<*>) = ap
-instance               Applicative (Exception i) where pure = return; (<*>) = ap
-instance               Applicative (Cont      i) where pure = return; (<*>) = ap
+instance Applicative (Reader i) where
+  pure = derive_return iso_R
+  (<*>) = ap
+
+instance (Monoid i) => Applicative (Writer i) where
+  pure = derive_return iso_W
+  (<*>) = ap
+
+instance Applicative (State i) where
+  pure = derive_return iso_S
+  (<*>) = ap
+
+instance Applicative (Exception i) where
+  pure = derive_return iso_X
+  (<*>) = ap
+
+instance Applicative (Cont i) where
+  pure = derive_return iso_C
+  (<*>) = ap
 
 instance               MonadFix (Reader    i) where mfix = derive_mfix iso_R
 instance (Monoid i) => MonadFix (Writer    i) where mfix = derive_mfix iso_W
