diff --git a/data-transform.cabal b/data-transform.cabal
--- a/data-transform.cabal
+++ b/data-transform.cabal
@@ -1,5 +1,5 @@
 name:                data-transform
-version:             0.1.0.2
+version:             0.1.1.0
 synopsis:            Functions to transform data structures.
 description:         This library provides a simple way to transform parts of
                      complex data structures. It is based on Data.Data.
@@ -22,14 +22,13 @@
                        MultiParamTypeClasses,
                        FunctionalDependencies,
                        UndecidableInstances
-  build-depends:       base >= 4.9 && < 5,
+  build-depends:       base >= 4.14 && < 5,
                        mtl,
                        containers
   hs-source-dirs:      src
-  ghc-options:         -Wall -fwarn-tabs -fwarn-incomplete-record-updates -fwarn-monomorphism-restriction -fwarn-incomplete-uni-patterns
+  ghc-options:         -Wall -fwarn-incomplete-record-updates -fwarn-monomorphism-restriction -fwarn-incomplete-uni-patterns
   default-language:    Haskell2010
 
 source-repository head
   type:     git
   location: git://github.com/ajscholl/data-transform.git
-
diff --git a/src/Data/Transform/Internal.hs b/src/Data/Transform/Internal.hs
--- a/src/Data/Transform/Internal.hs
+++ b/src/Data/Transform/Internal.hs
@@ -1,11 +1,11 @@
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE Trustworthy #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE GADTs                  #-}
+{-# LANGUAGE Trustworthy            #-}
+{-# LANGUAGE FlexibleInstances      #-}
+{-# LANGUAGE TypeFamilies           #-}
+{-# LANGUAGE LambdaCase             #-}
+{-# LANGUAGE MultiParamTypeClasses  #-}
 {-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE UndecidableInstances   #-}
 -----------------------------------------------------------------------------
 -- |
 -- Copyright   :  (c) 2014 Jonas Scholl
@@ -132,8 +132,8 @@
 
 -- | Same as 'appEndoList' but in a monadic context.
 appEndoListM :: (Monad m, Data a) => EndoListM m -> a -> m a
-appEndoListM NilM        a = return a
-appEndoListM (ConsM f l) a = maybe (return a) (liftM unsafeCoerce . f) (cast a) >>= appEndoListM l
+appEndoListM NilM        a = pure a
+appEndoListM (ConsM f l) a = maybe (pure a) (fmap unsafeCoerce . f) (cast a) >>= appEndoListM l
 
 -- | Class of transformations, i.e. objects containing endomorphisms.
 class Transformation d where
@@ -211,7 +211,7 @@
 
 -- | Same as 'transform' but with a monadic function. Calls 'fail' instead of
 --   'error' if a type-error is detected.
-transformM :: (MonadicTransformation d m, Data a) => d -> a -> m a
+transformM :: (MonadicTransformation d m, Data a, MonadFail m) => d -> a -> m a
 transformM d a = case mkEndoListM d of
     f -> case getNeededTypeRepsM f `Set.difference` allContainedTypeReps a of
         s | not (Set.null s) -> fail $ "Data.DataTraverse.transformM: Could not find all needed types when mapping over a value of type " ++ show (typeOf a) ++ ". Types of missing terms: " ++ show (Set.toList s)
@@ -271,7 +271,7 @@
 --   >>> getSubtermsBy (<6) (3, 4.0, True, 'c', (False, (True, 5, 6)))
 --   [3, 5]
 getSubtermsBy :: (Data a, Data b) => (b -> Bool) -> a -> [b]
-getSubtermsBy p = getSubtermsWith (\ x -> guard (p x) >> return [x])
+getSubtermsBy p = getSubtermsWith (\ x -> guard (p x) >> pure [x])
 
 -- | Returns all sub-terms (intermediate and non intermediate) of some type of a
 --   value which could be transformed to some 'Monoid'.
@@ -280,11 +280,26 @@
 --
 --   Example:
 --
---   >>> getSubtermsWith (\ x -> guard (x < 6) >> return [x]) (3, 4.0, True, 'c', (False, (True, 5, 6)))
+--   >>> getSubtermsWith (\ x -> guard (x < 6) >> pure [x]) (3, 4.0, True, 'c', (False, (True, 5, 6)))
 --   [3, 5]
 getSubtermsWith :: (Data a, Data b, Monoid m) => (b -> Maybe m) -> a -> m
-getSubtermsWith p = execWriter . transformM (\ x -> maybe (return ()) tell (p x) >> return x)
+getSubtermsWith p = runErrorIdentity . execWriterT . transformM (\ x -> maybe (pure ()) tell (p x) >> pure x)
 
+newtype ErrorIdentity a = ErrorIdentity { runErrorIdentity :: a }
+
+instance Functor ErrorIdentity where
+    fmap f (ErrorIdentity a) = ErrorIdentity (f a)
+
+instance Applicative ErrorIdentity where
+    pure = ErrorIdentity
+    (ErrorIdentity f) <*> (ErrorIdentity a) = ErrorIdentity (f a)
+
+instance Monad ErrorIdentity where
+    (ErrorIdentity a) >>= f = f a
+
+instance MonadFail ErrorIdentity where
+    fail = error
+
 ------------------
 -- * Type checking
 ------------------
@@ -308,7 +323,7 @@
     where
         helper :: Data a => a -> State (Set TypeRep) ()
         helper x = do
-            let subterms = execWriter $ gmapM (\ y -> tell [WrappedData y] >> return y) x
+            let subterms = execWriter $ gmapM (\ y -> tell [WrappedData y] >> pure y) x
             mapM_ (\ (WrappedData y) -> allContainedTypeReps' y) subterms
 
 -- | Construct a list of empty values, one for each constructor found in the data type.
