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
@@ -1,4 +1,4 @@
-{-# LANGUAGE BangPatterns, GeneralizedNewtypeDeriving, OverloadedStrings,
+{-# LANGUAGE CPP, BangPatterns, GeneralizedNewtypeDeriving, OverloadedStrings,
     Rank2Types, RecordWildCards, TypeFamilies #-}
 -- |
 -- Module      :  Data.Attoparsec.Internal.Types
@@ -39,7 +39,7 @@
 import Data.Text (Text)
 import qualified Data.Text as Text
 import Data.Text.Unsafe (Iter(..))
-import Prelude hiding (getChar, succ)
+import Prelude hiding (succ)
 import qualified Data.Attoparsec.ByteString.Buffer as B
 import qualified Data.Attoparsec.Text.Buffer as T
 
@@ -136,8 +136,10 @@
     mempty  = Incomplete
 
 instance Monad (Parser i) where
+#if !(MIN_VERSION_base(4,13,0))
     fail = Fail.fail
     {-# INLINE fail #-}
+#endif
 
     return = App.pure
     {-# INLINE return #-}
@@ -207,8 +209,9 @@
     {-# INLINE (<|>) #-}
 
     many v = many_v
-        where many_v = some_v <|> pure []
-              some_v = (:) App.<$> v <*> many_v
+      where
+        many_v = some_v <|> pure []
+        some_v = (:) <$> v <*> many_v
     {-# INLINE many #-}
 
     some v = some_v
diff --git a/Data/Attoparsec/Zepto.hs b/Data/Attoparsec/Zepto.hs
--- a/Data/Attoparsec/Zepto.hs
+++ b/Data/Attoparsec/Zepto.hs
@@ -92,8 +92,10 @@
         Fail err -> return (Fail err)
     {-# INLINE (>>=) #-}
 
+#if !(MIN_VERSION_base(4,13,0))
     fail = Fail.fail
     {-# INLINE fail #-}
+#endif
 
 instance Monad m => Fail.MonadFail (ZeptoT m) where
     fail msg = Parser $ \_ -> return (Fail msg)
diff --git a/attoparsec.cabal b/attoparsec.cabal
--- a/attoparsec.cabal
+++ b/attoparsec.cabal
@@ -1,12 +1,12 @@
 name:            attoparsec
-version:         0.13.2.2
+version:         0.13.2.3
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Parsing
 author:          Bryan O'Sullivan <bos@serpentine.com>
 maintainer:      Bryan O'Sullivan <bos@serpentine.com>, Ben Gamari <ben@smart-cactus.org>
 stability:       experimental
-tested-with:     GHC == 7.0.4, GHC == 7.2.2, GHC == 7.4.2, GHC ==7.6.3, GHC ==7.8.4, GHC ==7.10.3, GHC ==8.0.2, GHC ==8.2.2
+tested-with:     GHC == 7.0.4, GHC == 7.2.2, GHC == 7.4.2, GHC ==7.6.3, GHC ==7.8.4, GHC ==7.10.3, GHC ==8.0.2, GHC ==8.2.2, GHC==8.4.4, GHC==8.6.5, GHC==8.8.1
 synopsis:        Fast combinator parsing for bytestrings and text
 cabal-version:   >= 1.8
 homepage:        https://github.com/bos/attoparsec
@@ -39,7 +39,7 @@
 
 library
   build-depends: array,
-                 base >= 4.2 && < 5,
+                 base >= 4.3 && < 5,
                  bytestring,
                  containers,
                  deepseq,
@@ -124,10 +124,10 @@
 
   build-depends:
     array,
-    base >= 4 && < 5,
+    base,
     bytestring,
     deepseq >= 1.1,
-    QuickCheck >= 2.7 && < 2.10,
+    QuickCheck >= 2.13.2 && < 2.14,
     quickcheck-unicode,
     scientific,
     tasty >= 0.11,
diff --git a/benchmarks/HeadersByteString.hs b/benchmarks/HeadersByteString.hs
--- a/benchmarks/HeadersByteString.hs
+++ b/benchmarks/HeadersByteString.hs
@@ -9,6 +9,15 @@
 import qualified Data.Attoparsec.ByteString.Lazy as BL
 import qualified Data.ByteString.Char8 as B
 
+-- Note: In the benchmarks for parsing an http request
+-- from a strict bytestring, we consider warp's implementation,
+-- which has highly optimized code for handling the first
+-- line in particular. It's treatment of the headers
+-- is more relaxed from the treatment they are given by the
+-- attoparsec parser benchmarked here. Consequently, it
+-- is should not be possible to match its performance since
+-- it accepts header names with disallowed characters.
+
 headers :: IO Benchmark
 headers = do
   req <- B.readFile =<< pathTo "http-request.txt"
@@ -18,7 +27,7 @@
   return $ bgroup "headers" [
       bgroup "B" [
         bench "request" $ nf (B.parseOnly request) req
-      , bench "warp" $ nfIO (parseHeaderLines [req])
+      , bench "warp" $ nfIO (parseHeaderLines (B.split '\n' req))
       , bench "response" $ nf (B.parseOnly response) resp
       ]
     , bgroup "BL" [
diff --git a/benchmarks/HeadersByteString/Atto.hs b/benchmarks/HeadersByteString/Atto.hs
--- a/benchmarks/HeadersByteString/Atto.hs
+++ b/benchmarks/HeadersByteString/Atto.hs
@@ -15,8 +15,16 @@
 instance NFData HttpVersion where
     rnf !_ = ()
 
+isHeaderChar :: Char -> Bool
+isHeaderChar c =
+  (c >= 'a' && c <= 'z') ||
+  (c >= 'A' && c <= 'Z') ||
+  (c >= '0' && c <= '9') ||
+  (c == '_') ||
+  (c == '-')
+
 header = do
-  name <- B.takeWhile1 (B.inClass "a-zA-Z0-9_-") <* B.char ':' <* B.skipSpace
+  name <- B.takeWhile1 isHeaderChar <* B.char ':' <* B.skipSpace
   body <- bodyLine
   return (name, body)
 
diff --git a/benchmarks/http-request.txt b/benchmarks/http-request.txt
--- a/benchmarks/http-request.txt
+++ b/benchmarks/http-request.txt
@@ -1,14 +1,9 @@
 GET / HTTP/1.1
 Host: twitter.com
-Accept: text/html, application/xhtml+xml, application/xml; q=0.9,
-	image/webp, */*; q=0.8
+Accept: text/html, application/xhtml+xml, application/xml; q=0.9, image/webp, */*; q=0.8
 Accept-Encoding: gzip,deflate,sdch
 Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
 Cache-Control: max-age=0
-Cookie: guest_id=v1%3A139; _twitter_sess=BAh7CSIKZmxhc2hJQz-e1e1;
-	__utma=43838368.452555194.1399611824.1; __utmb=43838368;
-	__utmc=43838368; __utmz=1399611824.1.1.utmcsr=(direct)|utmcmd=(none)
-User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5)
-	AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.86
-	Safari/537.36
+Cookie: guest_id=v1%3A139; _twitter_sess=BAh7CSIKZmxhc2hJQz-e1e1; __utma=43838368.452555194.1399611824.1; __utmb=43838368; __utmc=43838368; __utmz=1399611824.1.1.utmcsr=(direct)|utmcmd=(none)
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.86 Safari/537.36
 
diff --git a/benchmarks/http-response.txt b/benchmarks/http-response.txt
--- a/benchmarks/http-response.txt
+++ b/benchmarks/http-response.txt
@@ -3,10 +3,8 @@
 Expires: -1
 Cache-Control: private, max-age=0
 Content-Type: text/html; charset=ISO-8859-1
-Set-Cookie: PREF=ID=1a871afc4240db5e:FF:LM=1399609497:S=e5MZ0itEekjVwNcU;
-	expires=Sun, 08-May-2016 04:24:57 GMT; path=/; domain=.google.com
-Set-Cookie: NID=67=-WlfaDG6VSEPk7abAjrK98HBSoCD2ID6JKkUR95tEumzDmg7Fc8pSQ8;
-	expires=Sat, 08-Nov-2014 04:24:57 GMT; path=/; domain=.google.com; HttpOnly
+Set-Cookie: PREF=ID=1a871afc4240db5e:FF:LM=1399609497:S=e5MZ0itEekjVwNcU; expires=Sun, 08-May-2016 04:24:57 GMT; path=/; domain=.google.com
+Set-Cookie: NID=67=-WlfaDG6VSEPk7abAjrK98HBSoCD2ID6JKkUR95tEumzDmg7Fc8pSQ8; expires=Sat, 08-Nov-2014 04:24:57 GMT; path=/; domain=.google.com; HttpOnly
 P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
 Server: gws
 X-XSS-Protection: 1; mode=block
diff --git a/tests/QC/ByteString.hs b/tests/QC/ByteString.hs
--- a/tests/QC/ByteString.hs
+++ b/tests/QC/ByteString.hs
@@ -26,9 +26,11 @@
 satisfy :: Word8 -> L.ByteString -> Property
 satisfy w s = parseBS (P.satisfy (<=w)) (L.cons w s) === Just w
 
-satisfyWith :: Char -> L.ByteString -> Property
-satisfyWith c s = parseBS (P.satisfyWith (chr . fromIntegral) (<=c))
+satisfyWith :: Word8 -> L.ByteString -> Property
+satisfyWith w s = parseBS (P.satisfyWith (chr . fromIntegral) (<=c))
                          (L.cons (fromIntegral (ord c)) s) === Just c
+  where
+    c = chr (fromIntegral w)
 
 word8 :: Word8 -> L.ByteString -> Property
 word8 w s = parseBS (P.word8 w) (L.cons w s) === Just w
diff --git a/tests/QC/Text.hs b/tests/QC/Text.hs
--- a/tests/QC/Text.hs
+++ b/tests/QC/Text.hs
@@ -6,6 +6,7 @@
 import Control.Applicative ((<*>), (<$>))
 #endif
 import Data.Int (Int64)
+import Data.Word (Word8)
 import Prelude hiding (take, takeWhile)
 import QC.Common (liftOp, parseT)
 import qualified QC.Text.FastSet as FastSet
@@ -16,8 +17,10 @@
 import qualified Data.Attoparsec.Text as P
 import qualified Data.Attoparsec.Text.Lazy as PL
 import qualified Data.Attoparsec.Text.FastSet as S
+import qualified Data.ByteString as BS
 import qualified Data.Char as Char
 import qualified Data.Text as T
+import qualified Data.Text.Encoding as TE
 import qualified Data.Text.Lazy as L
 
 -- Basic byte-level combinators.
@@ -70,9 +73,12 @@
     === Just t'
   where t' = toStrict t
 
-stringCI :: T.Text -> Property
-stringCI s = P.parseOnly (P.stringCI fs) s === Right s
+-- | Note: "simple, and efficient" works for well formed input...
+-- i.e. e.g. Latin1 texts
+stringCI :: [Word8] -> Property
+stringCI ws = P.parseOnly (P.stringCI fs) s === Right s
   where fs = T.toCaseFold s
+        s  = TE.decodeLatin1 (BS.pack ws)
 
 asciiCI :: T.Text -> Gen Bool
 asciiCI x =
@@ -150,7 +156,9 @@
                      (c, fst <$> L.uncons s') === ('\r', Just '\n')
 
 scan :: L.Text -> Positive Int64 -> Property
-scan s (Positive k) = parseT p s === Just (toStrict $ L.take k s)
+-- for some reason, if counterexample is removed, this test fails?
+scan s (Positive k) = counterexample (show s)
+                    $ parseT p s === Just (toStrict $ L.take k s)
   where p = P.scan k $ \ n _ ->
             if n > 0 then let !n' = n - 1 in Just n' else Nothing
 
