diff --git a/Data/Attoparsec/Combinator.hs b/Data/Attoparsec/Combinator.hs
--- a/Data/Attoparsec/Combinator.hs
+++ b/Data/Attoparsec/Combinator.hs
@@ -18,6 +18,7 @@
     , manyTill
     , sepBy
     , sepBy1
+    , foldSepBy
     , skipMany
     , skipMany1
     , eitherP
@@ -33,6 +34,7 @@
 
 import Control.Applicative (Alternative, Applicative(..), empty, liftA2,
                             (<|>), (*>), (<$>))
+import Control.Monad (MonadPlus(..))
 #if __GLASGOW_HASKELL__ >= 700
 import Data.Attoparsec.Internal.Types (Parser)
 import qualified Data.Attoparsec.Zepto as Z
@@ -89,6 +91,16 @@
 #if __GLASGOW_HASKELL__ >= 700
 {-# SPECIALIZE sepBy1 :: Parser a -> Parser s -> Parser [a] #-}
 {-# SPECIALIZE sepBy1 :: Z.Parser a -> Z.Parser s -> Z.Parser [a] #-}
+#endif
+
+foldSepBy :: (MonadPlus m) => (a -> m a) -> m z -> a -> m a
+foldSepBy p s z0 = go z0 `mplus` return z0
+  where go z = do
+          z' <- p z
+          (s >> go z') `mplus` return z'
+#if __GLASGOW_HASKELL__ >= 700
+{-# SPECIALIZE foldSepBy :: (a -> Parser a) -> Parser z -> a -> Parser a #-}
+{-# SPECIALIZE foldSepBy :: (a -> Z.Parser a) -> Z.Parser z -> a -> Z.Parser a #-}
 #endif
 
 -- | @manyTill p end@ applies action @p@ /zero/ or more times until
diff --git a/Data/Attoparsec/Internal.hs b/Data/Attoparsec/Internal.hs
--- a/Data/Attoparsec/Internal.hs
+++ b/Data/Attoparsec/Internal.hs
@@ -69,6 +69,7 @@
 import Data.Attoparsec.Combinator
 import Data.Attoparsec.FastSet (charClass, memberWord8)
 import Data.Attoparsec.Internal.Types
+import Data.Monoid (Monoid(..))
 import Data.Word (Word8)
 import Foreign.ForeignPtr (withForeignPtr)
 import Foreign.Ptr (castPtr, minusPtr, plusPtr)
@@ -98,7 +99,7 @@
 prompt i0 a0 _m0 kf ks = Partial $ \s ->
     if B.null s
     then kf i0 a0 Complete
-    else ks (I (unI i0 +++ s)) (A (unA a0 +++ s)) Incomplete
+    else ks (i0 <> I s) (a0 <> Added s) Incomplete
 
 -- | Immediately demand more input via a 'Partial' continuation
 -- result.
@@ -140,6 +141,19 @@
         noAdds i0 a0 m0 $ \i1 a1 m1 ->
             let kf' i2 a2 m2 = addS i0 a0 m0 i2 a2 m2 kf
             in runParser p i1 a1 m1 kf' ks
+  where noAdds i0 _a0 m0 f = f i0 mempty m0
+    
+addS :: Input -> Added -> More
+     -> Input -> Added -> More
+     -> (Input -> Added -> More -> r) -> r
+addS i0 a0 m0 _i1 a1 m1 f =
+    let !i = case a1 of
+               Dropped -> i0
+               Added s -> i0 <> I s
+        !a = a0 <> a1
+        !m = m0 <> m1
+    in f i a m
+{-# INLINE addS #-}
 
 -- | The parser @satisfy p@ succeeds for any byte for which the
 -- predicate @p@ returns 'True'. Returns the byte that is actually
@@ -356,7 +370,7 @@
   when (B.null h) $ fail "takeWhile1"
   put t
   if B.null t
-    then (h+++) `fmap` takeWhile p
+    then (h<>) <$> takeWhile p
     else return h
 
 -- | Match any byte in a set.
@@ -441,12 +455,12 @@
 
 -- | Run a parser.
 parse :: Parser a -> B.ByteString -> Result a
-parse m s = runParser m (I s) (A B.empty) Incomplete failK successK
+parse m s = runParser m (I s) mempty Incomplete failK successK
 {-# INLINE parse #-}
 
 -- | Run a parser that cannot be resupplied via a 'Partial' result.
 parseOnly :: Parser a -> B.ByteString -> Either String a
-parseOnly m s = case runParser m (I s) (A B.empty) Complete failK successK of
+parseOnly m s = case runParser m (I s) mempty Complete failK successK of
                   Fail _ _ err -> Left err
                   Done _ a     -> Right a
                   _            -> error "parseOnly: impossible error!"
diff --git a/Data/Attoparsec/Internal/Types.hs b/Data/Attoparsec/Internal/Types.hs
--- a/Data/Attoparsec/Internal/Types.hs
+++ b/Data/Attoparsec/Internal/Types.hs
@@ -20,9 +20,7 @@
     , Input(..)
     , Added(..)
     , More(..)
-    , addS
-    , noAdds
-    , (+++)
+    , (<>)
     ) where
 
 import Control.Applicative (Alternative(..), Applicative(..))
@@ -70,8 +68,22 @@
     {-# INLINE fmap #-}
 
 newtype Input = I {unI :: B.ByteString}
-newtype Added = A {unA :: B.ByteString}
+    deriving (Show)
 
+instance Monoid Input where
+    mempty              = I B.empty
+    mappend (I a) (I b) = I (a <> b)
+
+data Added = Dropped
+           | Added B.ByteString
+             deriving (Show)
+
+instance Monoid Added where
+    mempty                      = Dropped
+    mappend a@Dropped _         = a
+    mappend a         Dropped   = a
+    mappend (Added a) (Added b) = Added (a <> b)
+
 -- | The 'Parser' type is a monad.
 newtype Parser a = Parser {
       runParser :: forall r. Input -> Added -> More
@@ -87,19 +99,11 @@
 data More = Complete | Incomplete
             deriving (Eq, Show)
 
-addS :: Input -> Added -> More
-     -> Input -> Added -> More
-     -> (Input -> Added -> More -> r) -> r
-addS i0 a0 m0 _i1 a1 m1 f =
-    let !i = I (unI i0 +++ unA a1)
-        a  = A (unA a0 +++ unA a1)
-        !m = m0 <> m1
-    in f i a m
-  where
-    Complete <> _ = Complete
-    _ <> Complete = Complete
-    _ <> _        = Incomplete
-{-# INLINE addS #-}
+instance Monoid More where
+    mempty                    = Incomplete
+    mappend Complete _        = Complete
+    mappend _        Complete = Complete
+    mappend _        _        = Incomplete
 
 bindP :: Parser a -> (a -> Parser b) -> Parser b
 bindP m g =
@@ -116,16 +120,10 @@
     (>>=)  = bindP
     fail   = failDesc
 
-noAdds :: Input -> Added -> More
-       -> (Input -> Added -> More -> r) -> r
-noAdds i0 _a0 m0 f = f i0 (A B.empty) m0
-{-# INLINE noAdds #-}
-
 plus :: Parser a -> Parser a -> Parser a
 plus a b = Parser $ \i0 a0 m0 kf ks ->
-           let kf' i1 a1 m1 _ _ = addS i0 a0 m0 i1 a1 m1 $
-                                  \ i2 a2 m2 -> runParser b i2 a2 m2 kf ks
-           in  noAdds i0 a0 m0 $ \i2 a2 m2 -> runParser a i2 a2 m2 kf' ks
+           let kf' i1 a1 m1 _ _ = runParser b i1 a1 m1 kf ks
+           in  runParser a i0 a0 m0 kf' ks
 {-# INLINE plus #-}
 
 instance MonadPlus Parser where
@@ -180,6 +178,6 @@
     where msg = "Failed reading: " ++ err
 {-# INLINE failDesc #-}
 
-(+++) :: B.ByteString -> B.ByteString -> B.ByteString
-(+++) = B.append
-{-# INLINE (+++) #-}
+(<>) :: (Monoid a) => a -> a -> a
+(<>) = mappend
+{-# INLINE (<>) #-}
diff --git a/attoparsec.cabal b/attoparsec.cabal
--- a/attoparsec.cabal
+++ b/attoparsec.cabal
@@ -1,5 +1,5 @@
 name:            attoparsec
-version:         0.8.6.1
+version:         0.9.0.0
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Parsing
