diff --git a/bytestringparser-temporary.cabal b/bytestringparser-temporary.cabal
--- a/bytestringparser-temporary.cabal
+++ b/bytestringparser-temporary.cabal
@@ -1,5 +1,5 @@
 name:            bytestringparser-temporary
-version:         0.1.0
+version:         0.3.0
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Parsing
diff --git a/src/Data/ParserCombinators/Attoparsec/Char8.hs b/src/Data/ParserCombinators/Attoparsec/Char8.hs
--- a/src/Data/ParserCombinators/Attoparsec/Char8.hs
+++ b/src/Data/ParserCombinators/Attoparsec/Char8.hs
@@ -49,6 +49,7 @@
     , notChar
     , string
     , stringCI
+    , bytes
 
     -- * Parser converters.
     , eitherP
@@ -78,7 +79,7 @@
 import qualified Data.ParserCombinators.Attoparsec.Internal as I
 import Data.ParserCombinators.Attoparsec.Internal
     (Parser, ParseError, (<?>), parse, parseAt, parseTest, try, manyTill, eof,
-     skipMany, skipMany1, count, lookAhead, peek, sepBy, sepBy1, string,
+     skipMany, skipMany1, count, lookAhead, peek, sepBy, sepBy1,
      eitherP, getInput, getConsumed, takeAll, notEmpty, match, notFollowedBy)
 import Prelude hiding (takeWhile)
 
@@ -128,10 +129,20 @@
 notInClass s = not . inClass s
 {-# INLINE notInClass #-}
 
+-- | Satisfy a literal string.
+string :: String -> Parser LB.ByteString
+string = I.string . LB.pack
+{-# INLINE string #-}
+
 -- | Satisfy a literal string, ignoring case.
-stringCI :: LB.ByteString -> Parser LB.ByteString
-stringCI = I.stringTransform (LB.map toLower)
+stringCI :: String -> Parser LB.ByteString
+stringCI = I.stringTransform (LB.map toLower) . LB.pack
 {-# INLINE stringCI #-}
+
+-- | Satisfy a literal @ByteString@.
+bytes :: LB.ByteString -> Parser LB.ByteString
+bytes = I.string
+{-# INLINE bytes #-}
 
 -- | Consume characters while the predicate is true.
 takeWhile :: (Char -> Bool) -> Parser LB.ByteString
diff --git a/src/Data/ParserCombinators/Attoparsec/Internal.hs b/src/Data/ParserCombinators/Attoparsec/Internal.hs
--- a/src/Data/ParserCombinators/Attoparsec/Internal.hs
+++ b/src/Data/ParserCombinators/Attoparsec/Internal.hs
@@ -274,15 +274,17 @@
 takeWhile1 :: (Word8 -> Bool) -> Parser LB.ByteString
 takeWhile1 p = Parser $ \s@(S sb lb n) ->
                let (h, t) = SB.span p sb
-               in if SB.null t
-                  then case unParser (nextChunk *> takeWhile p) s of
-                         Left err -> Left err
-                         Right (xs, s') ->
-                             let bs = h +: xs
-                             in if LB.null bs
-                               then Left (sb +: lb, [])
-                               else Right (bs, s')
-                  else Right (oneChunk h, S t lb (n + length64 h))
+               in if SB.null h
+                  then Left (sb +: lb, [])
+                  else if SB.null t
+                       then case unParser (nextChunk *> takeWhile p) s of
+                              Left err -> Left err
+                              Right (xs, s') ->
+                                  let bs = h +: xs
+                                  in if LB.null bs
+                                    then Left (sb +: lb, [])
+                                    else Right (bs, s')
+                       else Right (oneChunk h, S t lb (n + length64 h))
 {-# INLINE takeWhile1 #-}
 
 -- | Skip over characters while the predicate is true.
@@ -325,6 +327,15 @@
 eitherP :: Parser a -> Parser b -> Parser (Either a b)
 eitherP a b = (Left <$> a) <|> (Right <$> b)
 {-# INLINE eitherP #-}
+
+eitherF p = Parser $ \s ->
+            case unParser p s of
+              Right (m, s') -> Right (Right m, s')
+              Left err -> Right (Left err, s)
+{-# INLINE eitherF #-}
+
+err strings = Parser $ \s@(S sb lb n) -> Left (sb +: lb, strings)
+{-# INLINE err #-}
 
 peek :: Parser a -> Parser (Maybe a)
 peek p = Parser $ \s ->
