diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for replace-megaparsec
 
+## 1.4.4.0 -- 2020-12-04
+
+Add `splitCapT` and `breakCapT`.
+
 ## 1.4.3.0 -- 2020-09-28
 
 Bugfix sepCap backtracking when sep fails
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -263,10 +263,9 @@
 let editThree :: Char -> MTL.State Int String
     editThree x = do
         i <- get
-        let i' = i+1
-        if i'<=3
+        if i<3
             then do
-                put i'
+                put $ i+1
                 pure [toUpper x]
             else pure [x]
 
@@ -288,7 +287,7 @@
 #!/usr/bin/env stack
 {- stack
   script
-  --resolver lts-15
+  --resolver lts-16
   --package megaparsec
   --package replace-megaparsec
 -}
diff --git a/replace-megaparsec.cabal b/replace-megaparsec.cabal
--- a/replace-megaparsec.cabal
+++ b/replace-megaparsec.cabal
@@ -1,5 +1,5 @@
 name:                replace-megaparsec
-version:             1.4.3.0
+version:             1.4.4.0
 cabal-version:       1.18
 synopsis:            Find, replace, and split string patterns with Megaparsec parsers (instead of regex)
 homepage:            https://github.com/jamesdbrock/replace-megaparsec
diff --git a/src/Replace/Megaparsec.hs b/src/Replace/Megaparsec.hs
--- a/src/Replace/Megaparsec.hs
+++ b/src/Replace/Megaparsec.hs
@@ -36,13 +36,10 @@
 --
 -- See the __replace-megaparsec__ package README for usage examples.
 --
--- == Special accelerated inputs
---
--- There are specialization re-write rules to speed up all functions in this
--- module when the input stream type @s@ is "Data.Text" or "Data.ByteString".
---
 -- == Type constraints
 --
+-- === output stream type @Tokens s@ = input stream type @s@
+--
 -- All functions in the __Running Parser__ section require the type of the
 -- stream of text that is input to be
 -- @'Text.Megaparsec.Stream.Stream' s@
@@ -58,12 +55,32 @@
 -- * "Data.ByteString"
 -- * "Data.ByteString.Lazy"
 --
--- Megaparsec parsers have an error type parameter @e@. When writing parsers
--- to be used by this module, the error type parameter @e@ should usually
+-- === Custom error type @e@ should be 'Data.Void'
+--
+-- Megaparsec parsers have a custom error data component @e@. When writing parsers
+-- to be used by this module, the custom error type @e@ should usually
 -- be 'Data.Void', because every function in this module expects a parser
 -- failure to occur on every token in a non-matching section of the input
--- stream, so parser failure error descriptions are not returned.
+-- stream, so parser failure error descriptions are not returned, and you'll
+-- never see the custom error information.
+--
+-- == Special fast input types
+--
+-- Functions in this module will be “fast” when the input stream
+-- type @s@ is:
+--
+-- * "Data.Text"
+-- * "Data.ByteString"
+--
+-- We mean “fast” in the same sense as 'Text.Megaparsec.MonadParsec':
+-- when returning subsections of the input stream,
+-- we return slices of the input stream data, rather than constructing a list
+-- of tokens and then building a new stream subsection from that list.
+-- This relies on implementation details of the stream representation,
+-- so there are specialization re-write rules in this module to make
+-- that possible without adding new typeclasses.
 
+
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE TypeFamilies #-}
@@ -77,16 +94,19 @@
   (
     -- * Running parser
     --
-    -- | Functions in this section are ways to run parsers. They take
+    -- | Functions in this section are /ways to run parsers/
+    -- (like 'Text.Megaparsec.runParser'). They take
     -- as arguments a @sep@ parser and some input, run the parser on the input,
     -- and return a result.
     breakCap
+  , breakCapT
   , splitCap
+  , splitCapT
   , streamEdit
   , streamEditT
     -- * Parser combinator
     --
-    -- | Functions in this section are parser combinators. They take
+    -- | Functions in this section are /parser combinators/. They take
     -- a @sep@ parser for an argument, combine @sep@ with another parser,
     -- and return a new parser.
   , anyTill
@@ -157,17 +177,37 @@
         -- ^ The input stream of text
     -> Maybe (s, a, s)
         -- ^ Maybe (prefix, parse_result, suffix)
-breakCap sep input =
-    case runParser pser "" input of
-        (Left _) -> Nothing
-        (Right x) -> Just x
+breakCap sep input = runIdentity $ breakCapT sep input
+{-# INLINABLE breakCap #-}
+
+-- |
+-- === Break on and capture one pattern
+--
+-- Monad transformer version of 'breakCap'.
+--
+-- The parser @sep@ will run in the underlying monad context.
+breakCapT
+    :: forall m e s a. (Ord e, Stream s, Tokens s ~ s, Monad m)
+    => ParsecT e s m a
+        -- ^ The pattern matching parser @sep@
+    -> s
+        -- ^ The input stream of text
+    -> m (Maybe (s, a, s))
+        -- ^ Maybe (prefix, parse_result, suffix)
+breakCapT sep input =
+    runParserT pser "" input >>= \case
+        (Left _) -> pure Nothing
+        (Right x) -> pure $ Just x
   where
     pser = do
       (prefix, cap) <- anyTill sep
       suffix <- getInput
       pure (prefix, cap, suffix)
-{-# INLINABLE breakCap #-}
+{-# INLINABLE breakCapT #-}
 
+
+
+
 -- |
 -- === Split on and capture all patterns
 --
@@ -199,20 +239,39 @@
 -- input == 'Data.Monoid.mconcat' ('Data.Bifunctor.second' 'Data.Tuple.fst' '<$>' output)
 -- @
 splitCap
-    :: forall e s a. (Ord e, Show e, Show (Token s), Stream s, Tokens s ~ s)
+    :: forall e s a. (Ord e, Stream s, Tokens s ~ s)
     => Parsec e s a
         -- ^ The pattern matching parser @sep@
     -> s
         -- ^ The input stream of text
     -> [Either s a]
         -- ^ List of matching and non-matching input sections.
-splitCap sep input = do
-    case runParser (sepCap sep) "" input of
-        (Left (ParseErrorBundle errs _)) -> error (show errs) -- undefined -- sepCap can never fail
-        (Right r) -> r
+splitCap sep input = runIdentity $ splitCapT sep input
 {-# INLINABLE splitCap #-}
 
+
 -- |
+-- === Split on and capture all patterns
+--
+-- Monad transformer version of 'splitCap'.
+--
+-- The parser @sep@ will run in the underlying monad context.
+splitCapT
+    :: forall e s m a. (Ord e, Stream s, Tokens s ~ s, Monad m)
+    => ParsecT e s m a
+        -- ^ The pattern matching parser @sep@
+    -> s
+        -- ^ The input stream of text
+    -> m [Either s a]
+        -- ^ List of matching and non-matching input sections.
+splitCapT sep input =
+    runParserT (sepCap sep) "" input >>= \case
+        (Left _) -> undefined -- sepCap can never fail
+        (Right r) -> pure r
+{-# INLINABLE splitCapT #-}
+
+
+-- |
 -- === Stream editor
 --
 -- Also known as “find-and-replace”, or “match-and-substitute”. Finds all
@@ -251,11 +310,11 @@
 {-# INLINABLE streamEdit #-}
 
 -- |
--- === Stream editor transformer
+-- === Stream editor
 --
 -- Monad transformer version of 'streamEdit'.
 --
--- Both the parser @sep@ and the @editor@ function run in the underlying
+-- Both the parser @sep@ and the @editor@ function will run in the underlying
 -- monad context.
 --
 -- If you want to do 'IO' operations in the @editor@ function or the
@@ -277,7 +336,7 @@
 streamEditT sep editor input = do
     runParserT (sepCap sep) "" input >>= \case
         (Left _) -> undefined -- sepCap can never fail
-        (Right r) -> fmap mconcat $ traverse (either return editor) r
+        (Right r) -> mconcat <$> traverse (either return editor) r
 {-# INLINABLE streamEditT #-}
 
 -- |
@@ -430,6 +489,7 @@
     -> m [Either (Tokens s) (Tokens s, a)] -- ^ parser
 findAllCap sep = sepCap (match sep)
 {-# INLINABLE findAllCap #-}
+{-# DEPRECATED findAllCap "replace with `findAllCap sep = sepCap (match sep)`" #-}
 
 
 -- |
@@ -452,3 +512,4 @@
     -> m [Either (Tokens s) (Tokens s)] -- ^ parser
 findAll sep = (fmap.fmap) (second fst) $ sepCap (match sep)
 {-# INLINABLE findAll #-}
+{-# DEPRECATED findAll "replace with `findAll sep = (fmap.fmap) (second fst) $ sepCap (match sep)`" #-}
diff --git a/tests/TestByteString.hs b/tests/TestByteString.hs
--- a/tests/TestByteString.hs
+++ b/tests/TestByteString.hs
@@ -17,10 +17,13 @@
 
 type Parser = Parsec Void B.ByteString
 
+findAllCap' :: MonadParsec e s m => m a -> m [Either (Tokens s) (Tokens s, a)]
+findAllCap' sep = sepCap (match sep)
+
 tests :: IO [Test]
 tests = return
     [ Test $ runParserTest "findAll upperChar"
-        (findAllCap (upperChar :: Parser Word8))
+        (findAllCap' (upperChar :: Parser Word8))
         ("aBcD" :: B.ByteString)
         [Left "a", Right ("B", c2w 'B'), Left "c", Right ("D", c2w 'D')]
     -- check that sepCap can progress even when parser consumes nothing
diff --git a/tests/TestString.hs b/tests/TestString.hs
--- a/tests/TestString.hs
+++ b/tests/TestString.hs
@@ -10,13 +10,20 @@
 import Text.Megaparsec
 import Text.Megaparsec.Char
 import Data.Void
+import Data.Bifunctor (second)
 
 type Parser = Parsec Void String
 
+findAllCap' :: MonadParsec e s m => m a -> m [Either (Tokens s) (Tokens s, a)]
+findAllCap' sep = sepCap (match sep)
+
+findAll' :: MonadParsec e s f => f b -> f [Either (Tokens s) (Tokens s)]
+findAll' sep = (fmap.fmap) (second fst) $ sepCap (match sep)
+
 tests :: IO [Test]
 tests = return
     [ Test $ runParserTest "findAll upperChar"
-        (findAllCap (upperChar :: Parser Char))
+        (findAllCap' (upperChar :: Parser Char))
         ("aBcD" :: String)
         [Left "a", Right ("B", 'B'), Left "c", Right ("D", 'D')]
     -- check that sepCap can progress even when parser consumes nothing
@@ -44,7 +51,7 @@
         ([Left "a"])
 #endif
     , Test $ runParserTest "findAll astral"
-        (findAll ((takeWhileP Nothing (=='𝅘𝅥𝅯') :: Parser String)))
+        (findAll' ((takeWhileP Nothing (=='𝅘𝅥𝅯') :: Parser String)))
         ("𝄞𝅘𝅥𝅘𝅥𝅘𝅥𝅘𝅥𝅘𝅥𝅯𝅘𝅥𝅯𝅘𝅥𝅯𝅘𝅥𝅯𝅘𝅥𝅘𝅥𝅘𝅥𝅘𝅥")
         [Left "𝄞𝅘𝅥𝅘𝅥𝅘𝅥𝅘𝅥", Right "𝅘𝅥𝅯𝅘𝅥𝅯𝅘𝅥𝅯𝅘𝅥𝅯", Left "𝅘𝅥𝅘𝅥𝅘𝅥𝅘𝅥"]
     , Test $ runParserTest "empty input" (sepCap (fail "" :: Parser ())) "" []
diff --git a/tests/TestText.hs b/tests/TestText.hs
--- a/tests/TestText.hs
+++ b/tests/TestText.hs
@@ -12,13 +12,20 @@
 import Text.Megaparsec.Char
 import Data.Void
 import qualified Data.Text as T
+import Data.Bifunctor (second)
 
 type Parser = Parsec Void T.Text
 
+findAllCap' :: MonadParsec e s m => m a -> m [Either (Tokens s) (Tokens s, a)]
+findAllCap' sep = sepCap (match sep)
+
+findAll' :: MonadParsec e s f => f b -> f [Either (Tokens s) (Tokens s)]
+findAll' sep = (fmap.fmap) (second fst) $ sepCap (match sep)
+
 tests :: IO [Test]
 tests = return
     [ Test $ runParserTest "findAll upperChar"
-        (findAllCap (upperChar :: Parser Char))
+        (findAllCap' (upperChar :: Parser Char))
         ("aBcD" :: T.Text)
         [Left "a", Right ("B", 'B'), Left "c", Right ("D", 'D')]
     -- check that sepCap can progress even when parser consumes nothing
@@ -46,7 +53,7 @@
         ([Left "a"])
 #endif
     , Test $ runParserTest "findAll astral"
-        (findAll ((takeWhileP Nothing (=='𝅘𝅥𝅯') :: Parser T.Text)))
+        (findAll' ((takeWhileP Nothing (=='𝅘𝅥𝅯') :: Parser T.Text)))
         ("𝄞𝅘𝅥𝅘𝅥𝅘𝅥𝅘𝅥𝅘𝅥𝅯𝅘𝅥𝅯𝅘𝅥𝅯𝅘𝅥𝅯𝅘𝅥𝅘𝅥𝅘𝅥𝅘𝅥" :: T.Text)
         [Left "𝄞𝅘𝅥𝅘𝅥𝅘𝅥𝅘𝅥", Right "𝅘𝅥𝅯𝅘𝅥𝅯𝅘𝅥𝅯𝅘𝅥𝅯", Left "𝅘𝅥𝅘𝅥𝅘𝅥𝅘𝅥"]
     , Test $ runParserTest "empty input" (sepCap (fail "" :: Parser ())) "" []
