diff --git a/Text/Trifecta/Diagnostic.hs b/Text/Trifecta/Diagnostic.hs
--- a/Text/Trifecta/Diagnostic.hs
+++ b/Text/Trifecta/Diagnostic.hs
@@ -1,17 +1,31 @@
 module Text.Trifecta.Diagnostic 
-  ( Diagnostic(..)
+  ( 
+  -- * Diagnostics
+    Diagnostic(..)
   , tellDiagnostic
-  , MonadDiagnostic(..)
-  , DiagnosticLevel(..)
+  -- * Rendering
   , Renderable(..)
   , Source
   , rendering
   , Caret(..), Careted(..)
   , Span(..), Spanned(..)
   , Fixit(..), Rendered(..)
+  -- * Emitting diagnostics
+  , MonadDiagnostic(..)
+  , fatal
+  , err
+  , warn
+  , note
+  , verbose
+  , warnWith
+  , noteWith
+  , verboseWith
+  -- * Diagnostic Levels
+  , DiagnosticLevel(..)
   ) where
 
 import Text.Trifecta.Diagnostic.Prim
 import Text.Trifecta.Diagnostic.Class
+import Text.Trifecta.Diagnostic.Combinators
 import Text.Trifecta.Diagnostic.Level
 import Text.Trifecta.Diagnostic.Rendering
diff --git a/Text/Trifecta/Diagnostic/Class.hs b/Text/Trifecta/Diagnostic/Class.hs
--- a/Text/Trifecta/Diagnostic/Class.hs
+++ b/Text/Trifecta/Diagnostic/Class.hs
@@ -6,28 +6,58 @@
 import Control.Monad.Trans.Class
 import Control.Monad.Trans.State.Lazy as Lazy
 import Control.Monad.Trans.State.Strict as Strict
+import Control.Monad.Trans.RWS.Lazy as Lazy
+import Control.Monad.Trans.RWS.Strict as Strict
+import Control.Monad.Trans.Writer.Lazy as Lazy
+import Control.Monad.Trans.Writer.Strict as Strict
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Identity
+import Data.Monoid
 import Text.Trifecta.Diagnostic.Prim
+import Text.Trifecta.Diagnostic.Level
+import Text.Trifecta.Diagnostic.Rendering.Prim
 
 class Monad m => MonadDiagnostic e m | m -> e where
-  record  :: Diagnostic e -> m ()
-  fatal   :: e -> m a -- consuming error
-  err     :: e -> m a -- non-consuming error
-  warn    :: e -> m ()
-  note    :: e -> m ()
-  verbose :: Int -> e -> m ()
+  fatalWith ::                    [Diagnostic e] -> [Rendering] -> e -> m a  -- consuming error
+  errWith   ::                    [Diagnostic e] -> [Rendering] -> e -> m a  -- non-consuming error, handled by <|> 
+  logWith   :: DiagnosticLevel -> [Diagnostic e] -> [Rendering] -> e -> m () -- log an error and continue
 
 instance MonadDiagnostic e m => MonadDiagnostic e (Lazy.StateT s m) where
-  record    = lift . record
-  fatal     = lift . fatal
-  err       = lift . err
-  warn      = lift . warn
-  note      = lift . note
-  verbose n = lift . verbose n
+  fatalWith d r e = lift (fatalWith d r e)
+  errWith   d r e = lift (errWith d r e)
+  logWith l d r e = lift (logWith l d r e)
 
 instance MonadDiagnostic e m => MonadDiagnostic e (Strict.StateT s m) where
-  record    = lift . record
-  fatal     = lift . fatal
-  err       = lift . err
-  warn      = lift . warn
-  note      = lift . note
-  verbose n = lift . verbose n
+  fatalWith d r e = lift (fatalWith d r e)
+  errWith   d r e = lift (errWith d r e)
+  logWith l d r e = lift (logWith l d r e)
+
+instance MonadDiagnostic e m => MonadDiagnostic e (ReaderT r m) where
+  fatalWith d r e = lift (fatalWith d r e)
+  errWith   d r e = lift (errWith d r e)
+  logWith l d r e = lift (logWith l d r e)
+
+instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Lazy.WriterT w m) where
+  fatalWith d r e = lift (fatalWith d r e)
+  errWith   d r e = lift (errWith d r e)
+  logWith l d r e = lift (logWith l d r e)
+
+instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Strict.WriterT w m) where
+  fatalWith d r e = lift (fatalWith d r e)
+  errWith   d r e = lift (errWith d r e)
+  logWith l d r e = lift (logWith l d r e)
+
+instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Lazy.RWST r w s m) where
+  fatalWith d r e = lift (fatalWith d r e)
+  errWith   d r e = lift (errWith d r e)
+  logWith l d r e = lift (logWith l d r e)
+
+instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Strict.RWST r w s m) where
+  fatalWith d r e = lift (fatalWith d r e)
+  errWith   d r e = lift (errWith d r e)
+  logWith l d r e = lift (logWith l d r e)
+
+instance MonadDiagnostic e m => MonadDiagnostic e (IdentityT m) where
+  fatalWith d r e = lift (fatalWith d r e)
+  errWith   d r e = lift (errWith d r e)
+  logWith l d r e = lift (logWith l d r e)
diff --git a/Text/Trifecta/Diagnostic/Combinators.hs b/Text/Trifecta/Diagnostic/Combinators.hs
new file mode 100644
--- /dev/null
+++ b/Text/Trifecta/Diagnostic/Combinators.hs
@@ -0,0 +1,45 @@
+module Text.Trifecta.Diagnostic.Combinators 
+  ( fatal
+  , err
+  , warn
+  , note
+  , verbose
+  , warnWith
+  , noteWith
+  , verboseWith
+  ) where
+
+import Text.Trifecta.Diagnostic.Class
+import Text.Trifecta.Diagnostic.Prim
+import Text.Trifecta.Diagnostic.Level
+import Text.Trifecta.Diagnostic.Rendering.Prim
+
+fatal :: MonadDiagnostic e m => e -> m a
+fatal = fatalWith [] []
+
+err :: MonadDiagnostic e m => e -> m a
+err = errWith [] []
+
+warn :: MonadDiagnostic e m => e -> m ()
+warn = warnWith [] []
+
+note :: MonadDiagnostic e m => e -> m ()
+note = noteWith [] []
+
+verbose :: MonadDiagnostic e m => Int -> e -> m ()
+verbose n = verboseWith n [] []
+
+warnWith :: MonadDiagnostic e m => [Diagnostic e] -> [Rendering] -> e -> m ()
+warnWith = logWith Warning
+
+noteWith :: MonadDiagnostic e m => [Diagnostic e] -> [Rendering] -> e -> m ()
+noteWith = logWith Note
+
+verboseWith :: MonadDiagnostic e m => Int -> [Diagnostic e] -> [Rendering] -> e -> m ()
+verboseWith n = logWith (Verbose n)
+
+-- sublimate :: MonadDiagnostic e m => m a -> m a
+-- sublimate a = a `catchError` \e -> 
+--   if fatalErr e then throwError e else do 
+--     m <- here
+--     tell (diagnose m e)
diff --git a/Text/Trifecta/Diagnostic/Err.hs b/Text/Trifecta/Diagnostic/Err.hs
--- a/Text/Trifecta/Diagnostic/Err.hs
+++ b/Text/Trifecta/Diagnostic/Err.hs
@@ -1,12 +1,9 @@
 module Text.Trifecta.Diagnostic.Err
   ( Err(..)
-  , diagnose
   , knownErr
   , fatalErr
   ) where
 
-import Control.Applicative
-import Control.Comonad
 import Data.Semigroup
 import Data.Monoid
 import Data.Functor.Plus
@@ -14,71 +11,32 @@
 import Text.Trifecta.Diagnostic.Level
 import Text.Trifecta.Diagnostic.Rendering.Prim
 import Text.PrettyPrint.Free
-import System.Console.Terminfo.PrettyPrint
 
--- | unlocated error messages
+-- | unlocated error
 data Err e
   = EmptyErr
-  | UnexpectedErr String
-  | EndOfFileErr
-  | FailErr String 
-  | RichErr (Rendering -> Diagnostic e) -- relocates with us as we try
-  | FatalErr (Diagnostic e)
-
-instance Show e => Show (Err e) where
-  showsPrec _ EmptyErr = showString "EmptyErr"
-  showsPrec d (FailErr s) = showParen (d > 10) $
-    showString "FailErr " . showsPrec 11 s
-  showsPrec d (UnexpectedErr s) = showParen (d > 10) $
-    showString "UnexpectedErr " . showsPrec 11 s
-  showsPrec d (FatalErr e) = showParen (d > 10) $ showString "FatalErr " . showsPrec 11 e
-  showsPrec _ EndOfFileErr = showString "EndOfFileErr"
-  showsPrec d (RichErr _) = showParen (d > 10) $ 
-    showString "RichErr ..."
+  | FailErr String
+  | Err     [Rendering] !DiagnosticLevel e [Diagnostic e]
+  deriving Show
 
 knownErr :: Err e -> Bool
 knownErr EmptyErr = False
 knownErr _ = True
 
 fatalErr :: Err e -> Bool
-fatalErr FatalErr{} = True
+fatalErr (Err _ Fatal _ _) = True
 fatalErr _ = False
 
-diagnose :: (t -> Doc e) -> Rendering -> Err t -> Diagnostic (Doc e)
-diagnose _ r EmptyErr          = Diagnostic r Error (text "unexpected") []
-diagnose _ r (FailErr m)       = Diagnostic r Error (fillSep $ text <$> words m) []
-diagnose _ r (UnexpectedErr s) = Diagnostic r Error (fillSep $ fmap text $ "unexpected" : words s) []
-diagnose _ r EndOfFileErr      = Diagnostic r Error (text "unexpected EOF") []
-diagnose k _ (FatalErr e)      = fmap k e
-diagnose k r (RichErr f)       = fmap k (f r)
-
-diagnose0 :: Pretty t => Err t -> Diagnostic (Doc e)
-diagnose0 = diagnose pretty emptyRendering
-
-diagnoseTerm0 :: PrettyTerm t => Err t -> Diagnostic TermDoc
-diagnoseTerm0 = diagnose prettyTerm emptyRendering
-
-instance Pretty t => Pretty (Err t) where
-  pretty = pretty . extract . diagnose0
-  prettyList = prettyList . map (extract . diagnose0)
-
-instance PrettyTerm t => PrettyTerm (Err t) where
-  prettyTerm = prettyTerm . diagnoseTerm0
-  prettyTermList = prettyTermList . map diagnoseTerm0
-  
 instance Functor Err where
   fmap _ EmptyErr = EmptyErr
   fmap _ (FailErr s) = FailErr s
-  fmap _ EndOfFileErr = EndOfFileErr
-  fmap f (FatalErr e) = FatalErr (fmap f e)
-  fmap _ (UnexpectedErr s) = UnexpectedErr s 
-  fmap f (RichErr k) = RichErr (fmap f . k)
+  fmap f (Err rs l e es) = Err rs l (f e) (fmap (fmap f) es)
 
 instance Alt Err where
-  EmptyErr     <!> a            = a
-  e@FatalErr{} <!> _            = e
-  _            <!> e@FatalErr{} = e
-  a            <!> _            = a 
+  a                   <!> EmptyErr            = a
+  _                   <!> a@(Err _ Fatal _ _) = a
+  a@(Err _ Fatal _ _) <!> _                   = a
+  _                   <!> b                   = b
   {-# INLINE (<!>) #-}
 
 instance Plus Err where
diff --git a/Text/Trifecta/Diagnostic/Err/State.hs b/Text/Trifecta/Diagnostic/Err/State.hs
--- a/Text/Trifecta/Diagnostic/Err/State.hs
+++ b/Text/Trifecta/Diagnostic/Err/State.hs
@@ -6,22 +6,23 @@
 import Data.Set as Set
 import Data.Semigroup
 import Data.Monoid
+import Text.PrettyPrint.Free
 import Text.Trifecta.Diagnostic.Err
 
 data ErrState e = ErrState
- { errExpected :: !(Set String)
- , errMessage  :: !(Err e)
+ { errExpected  :: !(Set String)
+ , errMessage   :: !(Err e)
  }
 
 instance Functor ErrState where
   fmap f (ErrState a b) = ErrState a (fmap f b)
 
 instance Alt ErrState where
-  ErrState a b <!> ErrState a' b' = ErrState (a <> a') (b <!> b')
+  ErrState a b <!> ErrState a' b' = ErrState (a <> a') (b <> b')
   {-# INLINE (<!>) #-}
 
 instance Plus ErrState where
-  zero = ErrState mempty zero
+  zero = ErrState mempty mempty
  
 instance Semigroup (ErrState e) where
   (<>) = (<!>) 
diff --git a/Text/Trifecta/Diagnostic/Level.hs b/Text/Trifecta/Diagnostic/Level.hs
--- a/Text/Trifecta/Diagnostic/Level.hs
+++ b/Text/Trifecta/Diagnostic/Level.hs
@@ -34,7 +34,7 @@
 
 instance PrettyTerm DiagnosticLevel where
   prettyTerm (Verbose n) = blue $ text "verbose (" <> int n <> char ')'
-  prettyTerm Note        = text "note"
+  prettyTerm Note        = black $ text "note"
   prettyTerm Warning     = magenta $ text "warning"
   prettyTerm Error       = red $ text "error"
-  prettyTerm Fatal       = blink $ red $ text "fatal"
+  prettyTerm Fatal       = standout $ red $ text "fatal"
diff --git a/Text/Trifecta/Parser/Class.hs b/Text/Trifecta/Parser/Class.hs
--- a/Text/Trifecta/Parser/Class.hs
+++ b/Text/Trifecta/Parser/Class.hs
@@ -18,6 +18,7 @@
   , (<?>)
   , slicedWith
   , sliced
+  , rend
   ) where
 
 import Control.Applicative
@@ -25,12 +26,22 @@
 import Control.Monad.Trans.Class
 import Control.Monad.Trans.State.Lazy as Lazy
 import Control.Monad.Trans.State.Strict as Strict
+import Control.Monad.Trans.Writer.Lazy as Lazy
+import Control.Monad.Trans.Writer.Strict as Strict
+import Control.Monad.Trans.RWS.Lazy as Lazy
+import Control.Monad.Trans.RWS.Strict as Strict
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Identity
+import Data.Monoid
+-- import Control.Monad.Trans.Maybe.Strict as Strict
+-- import Control.Monad.Trans.Either.Strict as Strict
 import Data.ByteString as Strict
 import Data.Semigroup
 import Data.Set as Set
 import Text.Trifecta.Rope.Delta
 import Text.Trifecta.Rope.Prim
 import Text.Trifecta.Parser.It
+import Text.Trifecta.Diagnostic.Rendering.Prim
 
 infix 0 <?>
 
@@ -72,6 +83,75 @@
   unexpected = lift . unexpected
   satisfyAscii = lift . satisfyAscii
 
+instance MonadParser m => MonadParser (ReaderT e m) where
+  satisfy = lift . satisfy
+  try (ReaderT m) = ReaderT $ try . m
+  labels (ReaderT m) ss = ReaderT $ \s -> labels (m s) ss
+  line = lift line
+  liftIt = lift . liftIt
+  mark = lift mark 
+  release = lift . release
+  unexpected = lift . unexpected
+  satisfyAscii = lift . satisfyAscii
+
+instance (MonadParser m, Monoid w) => MonadParser (Strict.WriterT w m) where
+  satisfy = lift . satisfy
+  try (Strict.WriterT m) = Strict.WriterT $ try m
+  labels (Strict.WriterT m) ss = Strict.WriterT $ labels m ss
+  line = lift line
+  liftIt = lift . liftIt
+  mark = lift mark 
+  release = lift . release
+  unexpected = lift . unexpected
+  satisfyAscii = lift . satisfyAscii
+
+instance (MonadParser m, Monoid w) => MonadParser (Lazy.WriterT w m) where
+  satisfy = lift . satisfy
+  try (Lazy.WriterT m) = Lazy.WriterT $ try m
+  labels (Lazy.WriterT m) ss = Lazy.WriterT $ labels m ss
+  line = lift line
+  liftIt = lift . liftIt
+  mark = lift mark 
+  release = lift . release
+  unexpected = lift . unexpected
+  satisfyAscii = lift . satisfyAscii
+
+instance (MonadParser m, Monoid w) => MonadParser (Lazy.RWST r w s m) where
+  satisfy = lift . satisfy
+  try (Lazy.RWST m) = Lazy.RWST $ \r s -> try (m r s)
+  labels (Lazy.RWST m) ss = Lazy.RWST $ \r s -> labels (m r s) ss
+  line = lift line
+  liftIt = lift . liftIt
+  mark = lift mark 
+  release = lift . release
+  unexpected = lift . unexpected
+  satisfyAscii = lift . satisfyAscii
+
+instance (MonadParser m, Monoid w) => MonadParser (Strict.RWST r w s m) where
+  satisfy = lift . satisfy
+  try (Strict.RWST m) = Strict.RWST $ \r s -> try (m r s)
+  labels (Strict.RWST m) ss = Strict.RWST $ \r s -> labels (m r s) ss
+  line = lift line
+  liftIt = lift . liftIt
+  mark = lift mark 
+  release = lift . release
+  unexpected = lift . unexpected
+  satisfyAscii = lift . satisfyAscii
+
+instance MonadParser m => MonadParser (IdentityT m) where
+  satisfy = lift . satisfy
+  try (IdentityT m) = IdentityT $ try m
+  labels (IdentityT m) = IdentityT . labels m
+  line = lift line
+  liftIt = lift . liftIt
+  mark = lift mark 
+  release = lift . release
+  unexpected = lift . unexpected
+  satisfyAscii = lift . satisfyAscii
+
+-- instance (MonadParser m, Monoid w) => MonadParser (MaybeT m) where
+-- instance (Error e, MonadParser m, Monoid w) => MonadParser (ErrorT e m) where
+
 -- useful when we've just recognized something out of band using access to the current line 
 skipping :: (MonadParser m, HasDelta d) => d -> m d
 skipping d = do
@@ -100,3 +180,5 @@
 sliced :: MonadParser m => m a -> m ByteString
 sliced = slicedWith (\_ bs -> bs)
   
+rend :: MonadParser m => m Rendering
+rend = rendering <$> mark <*> line
diff --git a/Text/Trifecta/Parser/Prim.hs b/Text/Trifecta/Parser/Prim.hs
--- a/Text/Trifecta/Parser/Prim.hs
+++ b/Text/Trifecta/Parser/Prim.hs
@@ -107,14 +107,13 @@
   {-# INLINE (>>=) #-}
   (>>) = (*>) 
   {-# INLINE (>>) #-}
-  fail = throwError . FailErr
+  fail s = Parser $ \ _ ee _ _ -> ee mempty { errMessage = FailErr s }
   {-# INLINE fail #-}
 
 instance MonadPlus (Parser e) where
   mzero = empty
   mplus = (<|>) 
 
-
 instance MonadWriter (Seq (Diagnostic e)) (Parser e) where
   tell w = Parser $ \eo _ _ _ l -> eo () mempty (l <> w)
   {-# INLINE tell #-}
@@ -133,28 +132,19 @@
       mempty
   {-# INLINE pass #-}
 
-logging :: DiagnosticLevel -> e -> Parser e ()
-logging level e = do
-  m <- mark
-  l <- line
-  tell $ return $ Diagnostic (addCaret m $ rendering m l) level e []
-
 instance MonadDiagnostic e (Parser e) where
-  record = tell . return
-  fatal e = Parser $ \_ _ _ ce l d bs -> ce mempty { errMessage = FatalErr (Diagnostic (addCaret d $ rendering d bs) Fatal e []) } l d bs
-  err e = do
-    m <- mark
-    throwError $ RichErr $ \r -> Diagnostic (addCaret m r) Error e [] -- showing the actual location
-  warn = logging Warning
-  note = logging Note
-  verbose = logging . Verbose
-
-instance MonadError (Err e) (Parser e) where
-  throwError m = Parser $ \_ ee _ _ -> ee mempty { errMessage = m } 
+  fatalWith ds rs e = Parser $ \_ _ _ ce -> 
+    ce mempty { errMessage = Err rs Fatal e ds }
+  errWith ds rs e = Parser $ \_ ee _ _ -> 
+    ee mempty { errMessage = Err rs Error e ds }
+  logWith v ds rs e = Parser $ \eo _ _ _ l d bs -> 
+    eo () mempty (l |> Diagnostic (addCaret d $ Prelude.foldr (<>) (rendering d bs) rs) v e ds) d bs
+    
+instance MonadError (ErrState e) (Parser e) where
+  throwError m = Parser $ \_ ee _ _ -> ee m
   {-# INLINE throwError #-}
   catchError (Parser m) k = Parser $ \ eo ee co ce -> 
-    m eo (\e -> unparser (k (errMessage e)) (\a e'-> eo a (e <> e')) (\e' -> ee (e <> e')) co ce) 
-      co ce
+    m eo (\e -> unparser (k e) eo ee co ce) co ce
   {-# INLINE catchError #-}
 
 instance MonadParser (Parser e) where
@@ -162,11 +152,11 @@
   try (Parser m) = Parser $ \ eo ee co ce -> m eo ee co $ 
     \e -> if fatalErr (errMessage e) then ce e else ee e
   {-# INLINE try #-}
-  unexpected s = Parser $ \ _ ee _ _ -> ee mempty { errMessage = UnexpectedErr s } 
+  unexpected s = Parser $ \ _ ee _ _ -> ee mempty { errMessage = FailErr $ "unexpected " ++ s }
 
   labels (Parser p) msgs = Parser $ \ eo ee -> p
-     (\a e -> eo a $ if knownErr (errMessage e) 
-                     then e { errExpected = errExpected e }
+     (\a e -> eo a $ if knownErr (errMessage e)
+                     then e { errExpected = msgs `union` errExpected e }
                      else e)
      (\e -> ee e { errExpected = msgs })
   {-# INLINE labels #-}
@@ -186,7 +176,7 @@
   {-# INLINE line #-}
   satisfy f = Parser $ \ _ ee co _ l d bs ->
     case UTF8.uncons $ Strict.drop (columnByte d) bs of
-      Nothing             -> ee mempty { errMessage = EndOfFileErr } l d bs
+      Nothing             -> ee mempty { errMessage = FailErr "unexpected EOF" } l d bs
       Just (c, xs) 
         | not (f c)       -> ee mempty l d bs
         | Strict.null xs  -> let ddc = d <> delta c in
@@ -201,7 +191,7 @@
         | b == Strict.length bs - 1 -> let ddc = d <> delta c in 
                                        join $ fillIt (co c mempty l ddc bs) (co c mempty l) ddc
         | otherwise                 -> co c mempty l (d <> delta c) bs
-    else ee mempty { errMessage = EndOfFileErr } l d bs
+    else ee mempty { errMessage = FailErr "unexpected EOF" } l d bs
   {-# INLINE satisfyAscii #-}
 
 data St e a = JuSt a !(ErrState e) !(ErrLog e) !Delta !ByteString
@@ -225,14 +215,16 @@
                                    NoSt e l d bs   -> Failure (yl <$> l) $ y e d bs) 
                                 (go <*> k)
 
-
--- explain an error in terms of the expected set, when we are running the step parser for pretty printing
 why :: Pretty e => (e -> Doc t) -> ErrState e -> Delta -> ByteString -> Diagnostic (Doc t)
 why pp (ErrState ss m) d bs 
-  | Set.null ss = diagnose pp (addCaret d $ rendering d bs) m
-  | otherwise   = expected <$> diagnose pp (addCaret d $ rendering d bs) m 
+  | Set.null ss = explicate m 
+  | otherwise   = expected <$> explicate m
   where
     expected doc = doc <> text ", expected" <+> fillSep (punctuate (char ',') $ text <$> toList ss)
+    r = addCaret d $ rendering d bs
+    explicate EmptyErr        = Diagnostic r Error (text "error") []
+    explicate (FailErr s)     = Diagnostic r Error (fillSep $ text <$> words s) []
+    explicate (Err rs l e es) = Diagnostic (addCaret d $ Prelude.foldr (<>) (rendering d bs) rs) l (pp e) (fmap (fmap pp) es)
 
 parseTest :: Show a => Parser String a -> String -> IO ()
 parseTest p s = case starve $ feed st $ UTF8.fromString s of
diff --git a/Text/Trifecta/Parser/Token/Class.hs b/Text/Trifecta/Parser/Token/Class.hs
--- a/Text/Trifecta/Parser/Token/Class.hs
+++ b/Text/Trifecta/Parser/Token/Class.hs
@@ -17,6 +17,13 @@
 import Control.Monad.Trans.Class
 import Control.Monad.Trans.State.Lazy as Lazy
 import Control.Monad.Trans.State.Strict as Strict
+import Control.Monad.Trans.Writer.Lazy as Lazy
+import Control.Monad.Trans.Writer.Strict as Strict
+import Control.Monad.Trans.RWS.Lazy as Lazy
+import Control.Monad.Trans.RWS.Strict as Strict
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Identity
+import Data.Monoid
 import Text.Trifecta.Parser.Class
 
 class MonadParser m => MonadTokenParser m where
@@ -44,6 +51,10 @@
   lexeme :: m a -> m a
   lexeme p = p <* whiteSpace
 
+instance MonadTokenParser m => MonadTokenParser (ReaderT r m) where
+  whiteSpace = lift whiteSpace
+  lexeme (ReaderT m) = ReaderT $ lexeme . m
+
 instance MonadTokenParser m => MonadTokenParser (Lazy.StateT s m) where
   whiteSpace = lift whiteSpace
   lexeme (Lazy.StateT m) = Lazy.StateT $ lexeme . m
@@ -51,3 +62,23 @@
 instance MonadTokenParser m => MonadTokenParser (Strict.StateT s m) where
   whiteSpace = lift whiteSpace
   lexeme (Strict.StateT m) = Strict.StateT $ lexeme . m
+
+instance (MonadTokenParser m, Monoid w) => MonadTokenParser (Lazy.WriterT w m) where
+  whiteSpace = lift whiteSpace
+  lexeme (Lazy.WriterT m) = Lazy.WriterT $ lexeme m
+
+instance (MonadTokenParser m, Monoid w) => MonadTokenParser (Strict.WriterT w m) where
+  whiteSpace = lift whiteSpace
+  lexeme (Strict.WriterT m) = Strict.WriterT $ lexeme m
+
+instance (MonadTokenParser m, Monoid w) => MonadTokenParser (Lazy.RWST r w s m) where
+  whiteSpace = lift whiteSpace
+  lexeme (Lazy.RWST m) = Lazy.RWST $ \r s -> lexeme (m r s)
+
+instance (MonadTokenParser m, Monoid w) => MonadTokenParser (Strict.RWST r w s m) where
+  whiteSpace = lift whiteSpace
+  lexeme (Strict.RWST m) = Strict.RWST $ \r s -> lexeme (m r s)
+
+instance MonadTokenParser m => MonadTokenParser (IdentityT m) where
+  whiteSpace = lift whiteSpace
+  lexeme = IdentityT . lexeme . runIdentityT
diff --git a/trifecta.cabal b/trifecta.cabal
--- a/trifecta.cabal
+++ b/trifecta.cabal
@@ -1,6 +1,6 @@
 name:          trifecta
 category:      Text, Parsing, Diagnostics, Pretty Printer, Logging
-version:       0.23
+version:       0.24
 license:       BSD3
 cabal-version: >= 1.6
 license-file:  LICENSE
@@ -38,6 +38,7 @@
     Text.Trifecta.Diagnostic
     Text.Trifecta.Diagnostic.Prim
     Text.Trifecta.Diagnostic.Class
+    Text.Trifecta.Diagnostic.Combinators
     Text.Trifecta.Diagnostic.Level
     Text.Trifecta.Diagnostic.Err
     Text.Trifecta.Diagnostic.Err.State
