diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,13 @@
+1.3.0.0 [2024-03-28]
+--------------------
+* Mini.Transformers.ParserT:
+    * Simplify and expose ParseError:
+        * Now a wrapper for {unexpected :: String}
+    * Prune redundant combinator 'chainl'
+    * Prune redundant combinator 'chainr'
+* docs: Remove code-cluttering examples
+    * Future work: separate 'examples' sections
+
 1.2.2.1 [2024-03-20]
 --------------------
 * docs: Add parser examples
diff --git a/Mini/Transformers/ParserT.hs b/Mini/Transformers/ParserT.hs
--- a/Mini/Transformers/ParserT.hs
+++ b/Mini/Transformers/ParserT.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE TupleSections #-}
 
@@ -8,7 +7,10 @@
   ParserT (
     ParserT
   ),
-  ParseError,
+  ParseError (
+    ParseError,
+    unexpected
+  ),
 
   -- * Runner
   runParserT,
@@ -27,9 +29,7 @@
   sepBy1,
   endBy,
   endBy1,
-  chainl,
   chainl1,
-  chainr,
   chainr1,
   between,
   option,
@@ -52,12 +52,6 @@
 import Data.Bool (
   bool,
  )
-import Data.Functor (
-  (<&>),
- )
-import Data.List (
-  intersperse,
- )
 import Mini.Transformers.Class (
   MonadTrans (
     lift
@@ -83,15 +77,15 @@
 
 -- | Parse @p@ or, if @p@ fails, backtrack and parse @q@ via @p \<|\> q@
 instance (Monad m, Eq s) => Alternative (ParserT s m) where
-  empty = ParserT . const . pure $ Left mempty
+  empty = ParserT . const . pure . Left $ ParseError empty
   m <|> n = ParserT $ \ss ->
     runParserT m ss
       >>= either
         ( \e1 ->
-            runParserT n ss
-              <&> either
-                (Left . mappend e1)
-                Right
+            either
+              (const $ Left e1)
+              Right
+              <$> runParserT n ss
         )
         (pure . Right)
 
@@ -104,7 +98,7 @@
           (\(a, ss') -> runParserT (k a) ss')
 
 instance MonadTrans (ParserT s) where
-  lift m = ParserT $ \ss -> m <&> Right . (,ss)
+  lift m = ParserT $ \ss -> Right . (,ss) <$> m
 
 -- | Combine the results of @p@ and @q@ via @p <> q@
 instance (Monad m, Semigroup a) => Semigroup (ParserT s m a) where
@@ -114,92 +108,47 @@
   mempty = pure mempty
 
 instance (Monad m) => MonadFail (ParserT s m) where
-  fail = ParserT . const . pure . Left . ParseError . pure
-
--- | Abstract representation of a parse error
-newtype ParseError = ParseError [String]
-  deriving (Semigroup, Monoid)
+  fail = ParserT . const . pure . Left . ParseError
 
-instance Show ParseError where
-  show (ParseError es) = "(parse error: " <> concat (intersperse ", " es) <> ")"
+-- | A parse error
+newtype ParseError = ParseError {unexpected :: String}
+  deriving (Show)
 
 {-
  - Parsers
  -}
 
-{- | Parse symbols satisfying a predicate
-
-=== __Examples__
-
->>> runParserT (some $ sat isDigit) "123abc"
-Right ("123","abc")
--}
+-- | Parse symbols satisfying a predicate
 sat :: (Applicative m, Show s) => (s -> Bool) -> ParserT s m s
 sat p = ParserT $ \case
-  [] -> pure . Left $ ParseError ["end of input"]
+  [] -> pure . Left $ ParseError []
   (s : ss) ->
     bool
-      (pure . Left $ ParseError ["unexpected " <> show s])
+      (pure . Left . ParseError $ show s)
       (pure $ Right (s, ss))
       $ p s
 
-{- | Parse any symbol
-
-=== __Examples__
-
->>> runParserT (item *> item <* item) "bar"
-Right ('a',"")
--}
+-- | Parse any symbol
 item :: (Applicative m, Show s) => ParserT s m s
 item = sat $ const True
 
-{- | Parse a symbol
-
-=== __Examples__
-
->>> runParserT (symbol 'f') "foo"
-Right ('f',"oo")
--}
+-- | Parse a symbol
 symbol :: (Applicative m, Show s, Eq s) => s -> ParserT s m s
 symbol = sat . (==)
 
-{- | Parse a sequence of symbols
-
-=== __Examples__
-
->>> runParserT (string "foo") "foobar"
-Right ("foo","bar")
--}
+-- | Parse a sequence of symbols
 string :: (Monad m, Traversable t, Show s, Eq s) => t s -> ParserT s m (t s)
 string = traverse symbol
 
-{- | Parse symbols included in a collection
-
-=== __Examples__
-
->>> runParserT (oneOf "abc") "bar"
-Right ('b',"ar")
--}
+-- | Parse symbols included in a collection
 oneOf :: (Applicative m, Foldable t, Show s, Eq s) => t s -> ParserT s m s
 oneOf = sat . flip elem
 
-{- | Parse symbols excluded from a collection
-
-=== __Examples__
-
->>> runParserT (noneOf "abc") "foo"
-Right ('f',"oo")
--}
+-- | Parse symbols excluded from a collection
 noneOf :: (Applicative m, Foldable t, Show s, Eq s) => t s -> ParserT s m s
 noneOf = sat . flip notElem
 
-{- | Parse successfully only at end of input
-
-=== __Examples__
-
->>> runParserT (string "foobar" *> eof) "foobar"
-Right ((),"")
--}
+-- | Parse successfully only at end of input
 eof :: (Monad m, Show s) => ParserT s m ()
 eof = reject item
 
@@ -207,68 +156,23 @@
  - Combinators
  -}
 
-{- | Parse zero or more @p@ separated by @q@ via @p \`sepBy\` q@
-
-=== __Examples__
-
->>> runParserT (sat isDigit `sepBy` symbol ',') "1,2,3,four"
-Right ("123",",four")
--}
+-- | Parse zero or more @p@ separated by @q@ via @p \`sepBy\` q@
 sepBy :: (Monad m, Eq s) => ParserT s m a -> ParserT s m b -> ParserT s m [a]
 sepBy p = option [] . sepBy1 p
 
-{- | Parse one or more @p@ separated by @q@ via @p \`sepBy1\` q@
-
-=== __Examples__
-
->>> runParserT (sat isDigit `sepBy1` symbol ',') "1,2,3,four"
-Right ("123",",four")
--}
+-- | Parse one or more @p@ separated by @q@ via @p \`sepBy1\` q@
 sepBy1 :: (Monad m, Eq s) => ParserT s m a -> ParserT s m b -> ParserT s m [a]
 sepBy1 p sep = (:) <$> p <*> many (sep *> p)
 
-{- | Parse zero or more @p@ separated and ended by @q@ via @p \`endBy\` q@
-
-=== __Examples__
-
->>> runParserT (sat isDigit `endBy` symbol ',') "1,2,3,four"
-Right ("123","four")
--}
+-- | Parse zero or more @p@ separated and ended by @q@ via @p \`endBy\` q@
 endBy :: (Monad m, Eq s) => ParserT s m a -> ParserT s m b -> ParserT s m [a]
 endBy p = option [] . endBy1 p
 
-{- | Parse one or more @p@ separated and ended by @q@ via @p \`endBy1\` q@
-
-=== __Examples__
-
->>> runParserT (sat isDigit `endBy1` symbol ',') "1,2,3,four"
-Right ("123","four")
--}
+-- | Parse one or more @p@ separated and ended by @q@ via @p \`endBy1\` q@
 endBy1 :: (Monad m, Eq s) => ParserT s m a -> ParserT s m b -> ParserT s m [a]
 endBy1 p sep = sepBy1 p sep <* sep
 
-{- | Parse zero or more @p@ left-chained with @op@ atop @a@ via @chainl p op a@
-
-=== __Examples__
-
->>> runParserT (chainl (read <$> some (sat isDigit)) ((+) <$ item) 10) "2a3b4c"
-Right (9,"c")
--}
-chainl
-  :: (Monad m, Eq s)
-  => ParserT s m a
-  -> ParserT s m (a -> a -> a)
-  -> a
-  -> ParserT s m a
-chainl p op a = option a $ chainl1 p op
-
-{- | Parse one or more @p@ left-chained with @op@ via @chainl1 p op@
-
-=== __Examples__
-
->>> runParserT (chainl1 (read <$> some (sat isDigit)) ((+) <$ item)) "2a3b4c"
-Right (9,"c")
--}
+-- | Parse one or more @p@ left-chained with @op@ via @chainl1 p op@
 chainl1
   :: (Monad m, Eq s)
   => ParserT s m a
@@ -278,28 +182,7 @@
  where
   go a = option a $ op <*> pure a <*> p >>= go
 
-{- | Parse zero or more @p@ right-chained with @op@ atop @a@ via @chainr p op a@
-
-=== __Examples__
-
->>> runParserT (chainr (read <$> some (sat isDigit)) ((*) <$ item) 10) "2a3b4c"
-Right (24,"c")
--}
-chainr
-  :: (Monad m, Eq s)
-  => ParserT s m a
-  -> ParserT s m (a -> a -> a)
-  -> a
-  -> ParserT s m a
-chainr p op a = option a $ chainr1 p op
-
-{- | Parse one or more @p@ right-chained with @op@ via @chainr1 p op@
-
-=== __Examples__
-
->>> runParserT (chainr1 (read <$> some (sat isDigit)) ((*) <$ item)) "2a3b4c"
-Right (24,"c")
--}
+-- | Parse one or more @p@ right-chained with @op@ via @chainr1 p op@
 chainr1
   :: (Monad m, Eq s)
   => ParserT s m a
@@ -310,13 +193,7 @@
   go = p >>= rest
   rest a = option a $ op <*> pure a <*> go >>= rest
 
-{- | Parse @p@ enclosed by @a@ and @b@ via @between a b p@
-
-=== __Examples__
-
->>> runParserT (between (symbol '(') (symbol ')') (many $ sat isLetter)) "(yes)"
-Right ("yes","")
--}
+-- | Parse @p@ enclosed by @a@ and @b@ via @between a b p@
 between
   :: (Monad m)
   => ParserT s m open
@@ -325,37 +202,19 @@
   -> ParserT s m a
 between open close p = open *> p <* close
 
-{- | Parse @p@ returning @a@ in case of failure via @option a p@
-
-=== __Examples__
-
->>> runParserT (option "foo" $ string "bar") "baz"
-Right ("foo","baz")
--}
+-- | Parse @p@ returning @a@ in case of failure via @option a p@
 option :: (Monad m, Eq s) => a -> ParserT s m a -> ParserT s m a
 option a p = p <|> pure a
 
-{- | Parse @p@, without consuming input, iff @p@ fails via @reject p@
-
-=== __Examples__
-
->>> runParserT (string "foo" <* reject (sat isLetter)) "foo(bar)"
-Right ("foo","(bar)")
--}
+-- | Parse @p@, without consuming input, iff @p@ fails via @reject p@
 reject :: (Monad m, Show a) => ParserT s m a -> ParserT s m ()
 reject p = ParserT $ \ss ->
   runParserT p ss
     >>= either
       (const . pure $ Right ((), ss))
-      (pure . Left . ParseError . pure . mappend "unexpected " . show . fst)
-
-{- | Parse @p@, without consuming input, iff @p@ succeeds via @accept p@
-
-=== __Examples__
+      (pure . Left . ParseError . show . fst)
 
->>> runParserT (accept item >>= pure . (== 'a')) "foo"
-Right (False,"foo")
--}
+-- | Parse @p@, without consuming input, iff @p@ succeeds via @accept p@
 accept :: (Monad m) => ParserT s m a -> ParserT s m a
 accept p = ParserT $ \ss ->
   runParserT p ss
diff --git a/Mini/Transformers/StateT.hs b/Mini/Transformers/StateT.hs
--- a/Mini/Transformers/StateT.hs
+++ b/Mini/Transformers/StateT.hs
@@ -27,9 +27,6 @@
   liftM,
   (>=>),
  )
-import Data.Functor (
-  (<&>),
- )
 import Mini.Transformers.Class (
   MonadTrans (
     lift
@@ -61,7 +58,7 @@
   m >>= k = StateT $ runStateT m >=> (\(a, s) -> runStateT (k a) s)
 
 instance MonadTrans (StateT s) where
-  lift m = StateT $ \s -> m <&> (,s)
+  lift m = StateT $ \s -> (,s) <$> m
 
 {-
  - Operations
diff --git a/Mini/Transformers/WriterT.hs b/Mini/Transformers/WriterT.hs
--- a/Mini/Transformers/WriterT.hs
+++ b/Mini/Transformers/WriterT.hs
@@ -24,9 +24,6 @@
   ap,
   liftM,
  )
-import Data.Functor (
-  (<&>),
- )
 import Mini.Transformers.Class (
   MonadTrans (
     lift
@@ -61,7 +58,7 @@
     pure (b, w <> w')
 
 instance (Monoid w) => MonadTrans (WriterT w) where
-  lift m = WriterT $ m <&> (,mempty)
+  lift = WriterT . fmap (,mempty)
 
 {-
  - Operations
diff --git a/mini.cabal b/mini.cabal
--- a/mini.cabal
+++ b/mini.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.4
 name:               mini
-version:            1.2.2.1
+version:            1.3.0.0
 license:            MIT
 license-file:       LICENSE
 copyright:          (c) 2023-2024 Victor Wallsten
