diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,21 @@
+## Version 0.5.0.0
+
+### Semantic changes
+
+ * Don't unecessarily quote spaces with `QuoteMinimal` (#118,#122,#86)
+ * Fix semantics of `foldl'` (#102)
+ * Fix field error diagnostics being mapped to `endOfInput` in `Parser` monad. (#99)
+ * Honor `encIncludeHeader` in incremental API (#136)
+
+### Other changes
+
+ * Support GHC 8.2.1
+ * Use factored-out `Only` package
+ * Add `FromField`/`ToField` instance for `ShortText`
+ * Add `MonadFail` and `Semigroup` instance for `Parser`
+ * Add `Semigroup` instance for incremental CSV API `Builder` & `NamedBuilder`
+ * Port to `ByteString` builder & drop dependency on `blaze-builder`
+
 ## Version 0.4.5.1
 
  * Restore GHC 7.4 support (#124)
diff --git a/Data/Csv/Builder.hs b/Data/Csv/Builder.hs
--- a/Data/Csv/Builder.hs
+++ b/Data/Csv/Builder.hs
@@ -18,7 +18,7 @@
 
 import Data.Monoid
 
-import Blaze.ByteString.Builder as Builder
+import Data.ByteString.Builder as Builder
 import Data.Csv.Conversion
 import qualified Data.Csv.Encoding as Encoding
 import Data.Csv.Encoding (EncodeOptions(..))
diff --git a/Data/Csv/Conversion.hs b/Data/Csv/Conversion.hs
--- a/Data/Csv/Conversion.hs
+++ b/Data/Csv/Conversion.hs
@@ -18,6 +18,14 @@
 {-# LANGUAGE PolyKinds #-}
 #endif
 
+#if !MIN_VERSION_bytestring(0,10,4)
+# define MIN_VERSION_text_short(a,b,c) 0
+#endif
+
+#if !defined(MIN_VERSION_text_short)
+# error **INVARIANT BROKEN** Detected invalid combination of `text-short` and `bytestring` versions. Please verify the `pre-bytestring-0.10-4` flag-logic in the .cabal file wasn't elided.
+#endif
+
 module Data.Csv.Conversion
     (
     -- * Type conversion
@@ -49,6 +57,7 @@
 
 import Control.Applicative (Alternative, (<|>), empty)
 import Control.Monad (MonadPlus, mplus, mzero)
+import qualified Control.Monad.Fail as Fail
 import Data.Attoparsec.ByteString.Char8 (double)
 import qualified Data.Attoparsec.ByteString.Char8 as A8
 import qualified Data.ByteString as B
@@ -62,10 +71,15 @@
 import Data.Int (Int8, Int16, Int32, Int64)
 import qualified Data.IntMap as IM
 import qualified Data.Map as M
+import Data.Semigroup (Semigroup, (<>))
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as T
 import qualified Data.Text.Lazy as LT
 import qualified Data.Text.Lazy.Encoding as LT
+#if MIN_VERSION_text_short(0,1,0)
+import qualified Data.Text.Short as T.S
+#endif
+import Data.Tuple.Only (Only(..))
 import Data.Vector (Vector, (!))
 import qualified Data.Vector as V
 import qualified Data.Vector.Unboxed as U
@@ -133,13 +147,6 @@
     default parseRecord :: (Generic a, GFromRecord (Rep a)) => Record -> Parser a
     parseRecord r = to <$> gparseRecord r
 
--- | Haskell lacks a single-element tuple type, so if you CSV data
--- with just one column you can use the 'Only' type to represent a
--- single-column result.
-newtype Only a = Only {
-      fromOnly :: a
-    } deriving (Eq, Ord, Read, Show)
-
 -- | A type that can be converted to a single CSV record.
 --
 -- An example type and instance:
@@ -872,6 +879,16 @@
     {-# INLINE toField #-}
 #endif
 
+#if MIN_VERSION_text_short(0,1,0)
+instance FromField T.S.ShortText where
+    parseField = maybe (fail "Invalid UTF-8 stream") pure . T.S.fromByteString
+    {-# INLINE parseField #-}
+
+instance ToField T.S.ShortText where
+    toField = T.S.toByteString
+    {-# INLINE toField #-}
+#endif
+
 -- | Assumes UTF-8 encoding. Fails on invalid byte sequences.
 instance FromField T.Text where
     parseField = either (fail . show) pure . T.decodeUtf8'
@@ -1037,6 +1054,10 @@
     {-# INLINE (>>) #-}
     return = pure
     {-# INLINE return #-}
+    fail = Fail.fail
+    {-# INLINE fail #-}
+
+instance Fail.MonadFail Parser where
     fail msg = Parser $ \kf _ks -> kf msg
     {-# INLINE fail #-}
 
@@ -1064,10 +1085,14 @@
                                    in unParser a kf' ks
     {-# INLINE mplus #-}
 
+instance Semigroup (Parser a) where
+    (<>) = mplus
+    {-# INLINE (<>) #-}
+
 instance Monoid (Parser a) where
     mempty  = fail "mempty"
     {-# INLINE mempty #-}
-    mappend = mplus
+    mappend = (<>)
     {-# INLINE mappend #-}
 
 apP :: Parser (a -> b) -> Parser a -> Parser b
diff --git a/Data/Csv/Conversion/Internal.hs b/Data/Csv/Conversion/Internal.hs
--- a/Data/Csv/Conversion/Internal.hs
+++ b/Data/Csv/Conversion/Internal.hs
@@ -3,8 +3,9 @@
     , realFloat
     ) where
 
-import Blaze.ByteString.Builder
-import Blaze.ByteString.Builder.Char8
+import Data.ByteString.Builder (Builder, toLazyByteString, word8, char8,
+                                string8, byteString)
+import qualified Data.ByteString.Builder.Prim as BP
 import Data.Array.Base (unsafeAt)
 import Data.Array.IArray
 import qualified Data.ByteString as B
@@ -13,11 +14,13 @@
 import Data.Monoid
 import Data.Word
 
+import Data.Csv.Util (toStrict)
+
 ------------------------------------------------------------------------
 -- Integers
 
 decimal :: Integral a => a -> B.ByteString
-decimal = toByteString . formatDecimal
+decimal = toStrict . toLazyByteString . formatDecimal
 {-# INLINE decimal #-}
 
 -- TODO: Add an optimized version for Integer.
@@ -80,13 +83,13 @@
              | otherwise = go (n `quot` 10) <> digit (n `rem` 10)
 
 minus :: Builder
-minus = fromWord8 45
+minus = word8 45
 
 zero :: Word8
 zero = 48
 
 digit :: Integral a => a -> Builder
-digit n = fromWord8 $! i2w (fromIntegral n)
+digit n = word8 $! i2w (fromIntegral n)
 {-# INLINE digit #-}
 
 i2w :: Int -> Word8
@@ -99,7 +102,7 @@
 realFloat :: RealFloat a => a -> B.ByteString
 {-# SPECIALIZE realFloat :: Float -> B.ByteString #-}
 {-# SPECIALIZE realFloat :: Double -> B.ByteString #-}
-realFloat = toByteString . formatRealFloat Generic
+realFloat = toStrict . toLazyByteString . formatRealFloat Generic
 
 -- | Control the rendering of floating point numbers.
 data FPFormat = Exponent
@@ -115,10 +118,10 @@
 {-# SPECIALIZE formatRealFloat :: FPFormat -> Float -> Builder #-}
 {-# SPECIALIZE formatRealFloat :: FPFormat -> Double -> Builder #-}
 formatRealFloat fmt x
-   | isNaN x                   = fromString "NaN"
+   | isNaN x                   = string8 "NaN"
    | isInfinite x              = if x < 0
-                                 then fromString "-Infinity"
-                                 else fromString "Infinity"
+                                 then string8 "-Infinity"
+                                 else string8 "Infinity"
    | x < 0 || isNegativeZero x = minus <> doFmt fmt (floatToDigits (-x))
    | otherwise                 = doFmt fmt (floatToDigits x)
  where
@@ -131,23 +134,23 @@
      Exponent ->
         let show_e' = formatDecimal (e-1) in
         case ds of
-          [48]    -> fromString "0.0e0"
-          [d]     -> fromWord8 d <> fromString ".0e" <> show_e'
-          (d:ds') -> fromWord8 d <> fromChar '.' <> fromWord8s ds' <>
-                     fromChar 'e' <> show_e'
+          [48]    -> string8 "0.0e0"
+          [d]     -> word8 d <> string8 ".0e" <> show_e'
+          (d:ds') -> word8 d <> char8 '.' <> word8s ds' <>
+                     char8 'e' <> show_e'
           []      -> error "formatRealFloat/doFmt/Exponent: []"
      Fixed
-          | e <= 0    -> fromString "0." <>
-                         fromByteString (B.replicate (-e) zero) <>
-                         fromWord8s ds
+          | e <= 0    -> string8 "0." <>
+                         byteString (B.replicate (-e) zero) <>
+                         word8s ds
           | otherwise ->
              let
-                f 0 s    rs  = mk0 (reverse s) <> fromChar '.' <> mk0 rs
+                f 0 s    rs  = mk0 (reverse s) <> char8 '.' <> mk0 rs
                 f n s    []  = f (n-1) (zero:s) []
                 f n s (r:rs) = f (n-1) (r:s) rs
              in
                 f e [] ds
-       where mk0 ls = case ls of { [] -> fromWord8 zero ; _ -> fromWord8s ls}
+       where mk0 ls = case ls of { [] -> word8 zero ; _ -> word8s ls}
 
 -- Based on "Printing Floating-Point Numbers Quickly and Accurately"
 -- by R.G. Burger and R.K. Dybvig in PLDI 96.
@@ -283,3 +286,7 @@
 {-# INLINE i2d #-}
 i2d :: Int -> Word8
 i2d i = fromIntegral (ord '0' + i)
+
+-- | Word8 list rendering
+word8s :: [Word8] -> Builder
+word8s = BP.primMapListFixed BP.word8
diff --git a/Data/Csv/Encoding.hs b/Data/Csv/Encoding.hs
--- a/Data/Csv/Encoding.hs
+++ b/Data/Csv/Encoding.hs
@@ -37,10 +37,8 @@
     , recordSep
     ) where
 
-import Blaze.ByteString.Builder (Builder, fromByteString, fromWord8,
-                                 toLazyByteString, toByteString)
-import Blaze.ByteString.Builder.Char8 (fromString)
-import Control.Applicative as AP (Applicative(..), (<|>), optional)
+import Data.ByteString.Builder
+import Control.Applicative as AP (Applicative(..), (<|>))
 import Data.Attoparsec.ByteString.Char8 (endOfInput)
 import qualified Data.Attoparsec.ByteString.Lazy as AL
 import qualified Data.ByteString as B
@@ -62,7 +60,7 @@
 import qualified Data.Csv.Parser as Parser
 import Data.Csv.Types hiding (toNamedRecord)
 import qualified Data.Csv.Types as Types
-import Data.Csv.Util (blankLine, endOfLine)
+import Data.Csv.Util (blankLine, endOfLine, toStrict)
 
 
 -- TODO: 'encode' isn't as efficient as it could be.
@@ -232,8 +230,8 @@
 -- | Encode a single record, without the trailing record separator
 -- (i.e. newline).
 encodeRecord :: Quoting -> Word8 -> Record -> Builder
-encodeRecord qtng delim = mconcat . intersperse (fromWord8 delim)
-                     . map fromByteString . map (escape qtng delim) . V.toList
+encodeRecord qtng delim = mconcat . intersperse (word8 delim)
+                     . map byteString . map (escape qtng delim) . V.toList
 {-# INLINE encodeRecord #-}
 
 -- | Encode a single named record, without the trailing record
@@ -246,23 +244,22 @@
 escape :: Quoting -> Word8 -> B.ByteString -> B.ByteString
 escape !qtng !delim !s
     | (qtng == QuoteMinimal &&
-        B.any (\ b -> b == dquote || b == delim || b == nl || b == cr || b == sp) s
+        B.any (\ b -> b == dquote || b == delim || b == nl || b == cr) s
       ) || qtng == QuoteAll
-         = toByteString $
-            fromWord8 dquote
+         = toStrict . toLazyByteString $
+            word8 dquote
             <> B.foldl
                 (\ acc b -> acc <> if b == dquote
-                    then fromByteString "\"\""
-                    else fromWord8 b)
+                    then byteString "\"\""
+                    else word8 b)
                 mempty
                 s
-            <> fromWord8 dquote
+            <> word8 dquote
     | otherwise = s
   where
     dquote = 34
     nl     = 10
     cr     = 13
-    sp     = 32
 
 -- | Like 'encodeByName', but lets you customize how the CSV data is
 -- encoded.
@@ -316,8 +313,8 @@
 {-# NOINLINE moduleError #-}
 
 recordSep :: Bool -> Builder
-recordSep False = fromWord8 10 -- new line (\n)
-recordSep True  = fromString "\r\n"
+recordSep False = word8 10 -- new line (\n)
+recordSep True  = string8 "\r\n"
 
 unlines :: Builder -> [Builder] -> Builder
 unlines _ [] = mempty
@@ -357,18 +354,16 @@
 csv :: FromRecord a => DecodeOptions -> AL.Parser (V.Vector a)
 csv !opts = do
     vals <- records
-    _ <- optional endOfLine
-    endOfInput
     return $! V.fromList vals
   where
     records = do
         !r <- record (decDelimiter opts)
         if blankLine r
-            then (endOfLine *> records) <|> pure []
+            then (endOfInput *> pure []) <|> (endOfLine *> records)
             else case runParser (parseRecord r) of
                 Left msg  -> fail $ "conversion error: " ++ msg
                 Right val -> do
-                    !vals <- (endOfLine *> records) <|> AP.pure []
+                    !vals <- (endOfInput *> AP.pure []) <|> (endOfLine *> records)
                     return (val : vals)
 {-# INLINE csv #-}
 
@@ -378,19 +373,17 @@
 csvWithHeader !opts = do
     !hdr <- header (decDelimiter opts)
     vals <- records hdr
-    _ <- optional endOfLine
-    endOfInput
     let !v = V.fromList vals
     return (hdr, v)
   where
     records hdr = do
         !r <- record (decDelimiter opts)
         if blankLine r
-            then (endOfLine *> records hdr) <|> pure []
+            then (endOfInput *> pure []) <|> (endOfLine *> records hdr)
             else case runParser (convert hdr r) of
                 Left msg  -> fail $ "conversion error: " ++ msg
                 Right val -> do
-                    !vals <- (endOfLine *> records hdr) <|> pure []
+                    !vals <- (endOfInput *> pure []) <|> (endOfLine *> records hdr)
                     return (val : vals)
 
     convert hdr = parseNamedRecord . Types.toNamedRecord hdr
diff --git a/Data/Csv/Incremental.hs b/Data/Csv/Incremental.hs
--- a/Data/Csv/Incremental.hs
+++ b/Data/Csv/Incremental.hs
@@ -83,9 +83,9 @@
 import qualified Data.Attoparsec.ByteString as A
 import Data.Attoparsec.ByteString.Char8 (endOfInput)
 import qualified Data.ByteString as B
-import qualified Blaze.ByteString.Builder as Builder
+import qualified Data.ByteString.Builder as Builder
 import qualified Data.ByteString.Lazy as L
-import Data.Monoid ((<>))
+import Data.Semigroup (Semigroup, (<>))
 import qualified Data.Vector as V
 import Data.Word (Word8)
 
@@ -344,12 +344,15 @@
       runBuilder :: Quoting -> Word8 -> Bool -> Builder.Builder
     }
 
-instance Monoid (Builder a) where
-    mempty = Builder (\ _ _ _ -> mempty)
-    mappend (Builder f) (Builder g) =
+instance Semigroup (Builder a) where
+    Builder f <> Builder g =
         Builder $ \ qtng delim useCrlf ->
         f qtng delim useCrlf <> g qtng delim useCrlf
 
+instance Monoid (Builder a) where
+    mempty  = Builder (\ _ _ _ -> mempty)
+    mappend = (<>)
+
 ------------------------------------------------------------------------
 -- ** Index-based record conversion
 
@@ -373,10 +376,15 @@
                  -> L.ByteString
 encodeByNameWith opts hdr b =
     Builder.toLazyByteString $
-    Encoding.encodeRecord (encQuoting opts) (encDelimiter opts) hdr <>
-    recordSep (encUseCrLf opts) <>
+    encHdr <>
     runNamedBuilder b hdr (encQuoting opts) (encDelimiter opts)
     (encUseCrLf opts)
+  where
+    encHdr
+      | encIncludeHeader opts =
+          Encoding.encodeRecord (encQuoting opts) (encDelimiter opts) hdr
+          <> recordSep (encUseCrLf opts)
+      | otherwise = mempty
 
 -- | Like 'encodeDefaultOrderedByName', but lets you customize how the
 -- CSV data is encoded.
@@ -385,12 +393,18 @@
     EncodeOptions -> NamedBuilder a -> L.ByteString
 encodeDefaultOrderedByNameWith opts b =
     Builder.toLazyByteString $
-    Encoding.encodeRecord (encQuoting opts) (encDelimiter opts) hdr <>
-    recordSep (encUseCrLf opts) <>
+    encHdr <>
     runNamedBuilder b hdr (encQuoting opts)
     (encDelimiter opts) (encUseCrLf opts)
-  where hdr = Conversion.headerOrder (undefined :: a)
+  where
+    hdr = Conversion.headerOrder (undefined :: a)
 
+    encHdr
+      | encIncludeHeader opts =
+          Encoding.encodeRecord (encQuoting opts) (encDelimiter opts) hdr
+          <> recordSep (encUseCrLf opts)
+      | otherwise = mempty
+
 -- | Encode a single named record.
 encodeNamedRecord :: ToNamedRecord a => a -> NamedBuilder a
 encodeNamedRecord nr = NamedBuilder $ \ hdr qtng delim useCrLf ->
@@ -406,11 +420,14 @@
       runNamedBuilder :: Header -> Quoting -> Word8 -> Bool -> Builder.Builder
     }
 
-instance Monoid (NamedBuilder a) where
-    mempty = NamedBuilder (\ _ _ _ _ -> mempty)
-    mappend (NamedBuilder f) (NamedBuilder g) =
+instance Semigroup (NamedBuilder a) where
+    NamedBuilder f <> NamedBuilder g =
         NamedBuilder $ \ hdr qtng delim useCrlf ->
         f hdr qtng delim useCrlf <> g hdr qtng delim useCrlf
+
+instance Monoid (NamedBuilder a) where
+    mempty = NamedBuilder (\ _ _ _ _ -> mempty)
+    mappend = (<>)
 
 ------------------------------------------------------------------------
 
diff --git a/Data/Csv/Parser.hs b/Data/Csv/Parser.hs
--- a/Data/Csv/Parser.hs
+++ b/Data/Csv/Parser.hs
@@ -24,8 +24,7 @@
     , field
     ) where
 
-import Blaze.ByteString.Builder (fromByteString, toByteString)
-import Blaze.ByteString.Builder.Char.Utf8 (fromChar)
+import Data.ByteString.Builder (byteString, toLazyByteString, charUtf8)
 import Control.Applicative (optional)
 import Data.Attoparsec.ByteString.Char8 (char, endOfInput)
 import qualified Data.Attoparsec.ByteString as A
@@ -37,7 +36,7 @@
 import Data.Word (Word8)
 
 import Data.Csv.Types
-import Data.Csv.Util ((<$!>), blankLine, endOfLine, liftM2', cr, newline, doubleQuote)
+import Data.Csv.Util ((<$!>), blankLine, endOfLine, liftM2', cr, newline, doubleQuote, toStrict)
 
 #if !MIN_VERSION_base(4,8,0)
 import Control.Applicative ((<$>), (*>), (<*), pure)
@@ -177,16 +176,16 @@
 dquote = char '"'
 
 unescape :: Z.Parser S.ByteString
-unescape = toByteString <$!> go mempty where
+unescape = (toStrict . toLazyByteString) <$!> go mempty where
   go acc = do
     h <- Z.takeWhile (/= doubleQuote)
     let rest = do
           start <- Z.take 2
           if (S.unsafeHead start == doubleQuote &&
               S.unsafeIndex start 1 == doubleQuote)
-              then go (acc `mappend` fromByteString h `mappend` fromChar '"')
+              then go (acc `mappend` byteString h `mappend` charUtf8 '"')
               else fail "invalid CSV escape sequence"
     done <- Z.atEnd
     if done
-      then return (acc `mappend` fromByteString h)
+      then return (acc `mappend` byteString h)
       else rest
diff --git a/Data/Csv/Streaming.hs b/Data/Csv/Streaming.hs
--- a/Data/Csv/Streaming.hs
+++ b/Data/Csv/Streaming.hs
@@ -115,6 +115,7 @@
 foldlRecords' f = go
   where
     go z (Cons (Right x) rs) = let z' = f z x in z' `seq` go z' rs
+    go z (Cons (Left _) rs) = go z rs
     go z _ = z
 {-# INLINE foldlRecords' #-}
 #endif
diff --git a/Data/Csv/Util.hs b/Data/Csv/Util.hs
--- a/Data/Csv/Util.hs
+++ b/Data/Csv/Util.hs
@@ -8,6 +8,7 @@
     , doubleQuote
     , newline
     , cr
+    , toStrict
     ) where
 
 import Control.Applicative ((<|>))
@@ -20,6 +21,15 @@
 
 #if !MIN_VERSION_base(4,8,0)
 import Control.Applicative ((*>))
+#endif
+
+#if MIN_VERSION_bytestring(0,10,0)
+import Data.ByteString.Lazy (toStrict)
+#else
+import qualified Data.ByteString.Lazy as L
+
+toStrict :: L.ByteString -> B.ByteString
+toStrict = B.concat . L.toChunks
 #endif
 
 -- | A strict version of 'Data.Functor.<$>' for monads.
diff --git a/benchmarks/Benchmarks.hs b/benchmarks/Benchmarks.hs
deleted file mode 100644
--- a/benchmarks/Benchmarks.hs
+++ /dev/null
@@ -1,156 +0,0 @@
-{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, OverloadedStrings,
-             RecordWildCards, TypeSynonymInstances #-}
-{-# OPTIONS_GHC -funbox-strict-fields #-}
-
-module Main ( main ) where
-
-import Control.Applicative as AP
-import Control.Exception (evaluate)
-import Control.DeepSeq
-import Criterion.Main
-import Data.ByteString (ByteString)
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as BL
-import qualified Data.HashMap.Strict as HM
-import Control.Monad (mzero)
-import Data.Text (Text)
-import qualified Text.CSV.Lazy.ByteString as LazyCsv
-import Data.Vector (Vector)
-import qualified Data.Vector as V
-
-import Data.Csv
-import qualified Data.Csv.Streaming as Streaming
-
-#if !MIN_VERSION_bytestring(0,10,0)
-instance NFData (B.ByteString) where
-    rnf !s = ()
-#endif
-
-data President = President
-                 { presidency     :: !Int
-                 , president      :: !Text
-                 , wikipediaEntry :: !ByteString
-                 , tookOffice     :: !ByteString
-                 , leftOffice     :: !ByteString
-                 , party          :: !Text
-                 , homeState      :: !Text
-                 }
-
-instance NFData President where
-    rnf (President {}) = ()
-
-instance FromRecord President where
-    parseRecord v
-        | V.length v == 7 = President <$>
-                            v .!! 0 AP.<*>
-                            v .!! 1 <*>
-                            v .!! 2 <*>
-                            v .!! 3 <*>
-                            v .!! 4 <*>
-                            v .!! 5 <*>
-                            v .!! 6
-        | otherwise       = mzero
-
--- | Unchecked version of '(.!)'.
-(.!!) :: FromField a => Record -> Int -> Parser a
-v .!! idx = parseField (V.unsafeIndex v idx)
-{-# INLINE (.!!) #-}
-infixl 9 .!!
-
-instance ToRecord President where
-    toRecord (President {..}) =
-        record [toField presidency, toField president, toField wikipediaEntry,
-                toField tookOffice, toField leftOffice, toField party,
-                toField homeState]
-
-instance FromNamedRecord President where
-    parseNamedRecord m = President <$>
-                         m .: "Presidency" <*>
-                         m .: "President" <*>
-                         m .: "Wikipedia Entry" <*>
-                         m .: "Took office" <*>
-                         m .: "Left office" <*>
-                         m .: "Party" <*>
-                         m .: "Home State"
-
-instance ToNamedRecord President where
-    toNamedRecord (President {..}) = namedRecord
-        [ "Presidency"      .= presidency
-        , "President"       .= president
-        , "Wikipedia Entry" .= wikipediaEntry
-        , "Took office"     .= tookOffice
-        , "Left office"     .= leftOffice
-        , "Party"           .= party
-        , "Home State"      .= homeState
-        ]
-
-fromStrict :: B.ByteString -> BL.ByteString
-fromStrict s = BL.fromChunks [s]
-
-type BSHashMap a = HM.HashMap B.ByteString a
-
-instance NFData LazyCsv.CSVField where
-    rnf LazyCsv.CSVField {} = ()
-    rnf LazyCsv.CSVFieldError {} = ()
-
-instance NFData LazyCsv.CSVError where
-    rnf (LazyCsv.IncorrectRow !_ !_ !_ xs) = rnf xs
-    rnf (LazyCsv.BlankLine _ _ _ field)    = rnf field
-    rnf (LazyCsv.FieldError field)         = rnf field
-    rnf (LazyCsv.DuplicateHeader _ _ s)    = rnf s
-    rnf LazyCsv.NoData                     = ()
-
-main :: IO ()
-main = do
-    !csvData <- fromStrict `fmap` B.readFile "benchmarks/presidents.csv"
-    !csvDataN <- fromStrict `fmap` B.readFile
-                 "benchmarks/presidents_with_header.csv"
-    let (Right !presidents) = V.toList <$> decodePresidents csvData
-        (Right (!hdr, !presidentsNV)) = decodePresidentsN csvDataN
-        !presidentsN = V.toList presidentsNV
-    evaluate (rnf [presidents, presidentsN])
-    defaultMain [
-          bgroup "positional"
-          [ bgroup "decode"
-            [ bench "presidents/without conversion" $ whnf idDecode csvData
-            , bench "presidents/with conversion" $ whnf decodePresidents csvData
-            , bgroup "streaming"
-              [ bench "presidents/without conversion" $ nf idDecodeS csvData
-              , bench "presidents/with conversion" $ nf decodePresidentsS csvData
-              ]
-            ]
-          , bgroup "encode"
-            [ bench "presidents/with conversion" $ whnf encode presidents
-            ]
-          ]
-        , bgroup "named"
-          [ bgroup "decode"
-            [ bench "presidents/without conversion" $ whnf idDecodeN csvDataN
-            , bench "presidents/with conversion" $ whnf decodePresidentsN csvDataN
-            ]
-          , bgroup "encode"
-            [ bench "presidents/with conversion" $ whnf (encodeByName hdr) presidentsN
-            ]
-          ]
-        , bgroup "comparison"
-          [ bench "lazy-csv" $ nf LazyCsv.parseCSV csvData
-          ]
-        ]
-  where
-    decodePresidents :: BL.ByteString -> Either String (Vector President)
-    decodePresidents = decode NoHeader
-
-    decodePresidentsN :: BL.ByteString -> Either String (Header, Vector President)
-    decodePresidentsN = decodeByName
-
-    decodePresidentsS :: BL.ByteString -> Streaming.Records President
-    decodePresidentsS = Streaming.decode NoHeader
-
-    idDecode :: BL.ByteString -> Either String (Vector (Vector B.ByteString))
-    idDecode = decode NoHeader
-
-    idDecodeN :: BL.ByteString -> Either String (Header, Vector (BSHashMap B.ByteString))
-    idDecodeN = decodeByName
-
-    idDecodeS :: BL.ByteString -> Streaming.Records (Vector B.ByteString)
-    idDecodeS = Streaming.decode NoHeader
diff --git a/benchmarks/presidents.csv b/benchmarks/presidents.csv
deleted file mode 100644
--- a/benchmarks/presidents.csv
+++ /dev/null
@@ -1,44 +0,0 @@
-1,George Washington,http://en.wikipedia.org/wiki/George_Washington,30/04/1789,04/03/1797,Independent,Virginia
-2,John Adams,http://en.wikipedia.org/wiki/John_Adams,04/03/1797,04/03/1801,Federalist,Massachusetts
-3,Thomas Jefferson,http://en.wikipedia.org/wiki/Thomas_Jefferson,04/03/1801,04/03/1809,Democratic-Republican,Virginia
-4,James Madison,http://en.wikipedia.org/wiki/James_Madison,04/03/1809,04/03/1817,Democratic-Republican,Virginia
-5,James Monroe,http://en.wikipedia.org/wiki/James_Monroe,04/03/1817,04/03/1825,Democratic-Republican,Virginia
-6,John Quincy Adams,http://en.wikipedia.org/wiki/John_Quincy_Adams,04/03/1825,04/03/1829,Democratic-Republican/National Republican,Massachusetts
-7,Andrew Jackson,http://en.wikipedia.org/wiki/Andrew_Jackson,04/03/1829,04/03/1837,Democratic,Tennessee
-8,Martin Van Buren,http://en.wikipedia.org/wiki/Martin_Van_Buren,04/03/1837,04/03/1841,Democratic,New York
-9,William Henry Harrison,http://en.wikipedia.org/wiki/William_Henry_Harrison,04/03/1841,04/04/1841,Whig,Ohio
-10,John Tyler,http://en.wikipedia.org/wiki/John_Tyler,04/04/1841,04/03/1845,Whig,Virginia
-11,James K. Polk,http://en.wikipedia.org/wiki/James_K._Polk,04/03/1845,04/03/1849,Democratic,Tennessee
-12,Zachary Taylor,http://en.wikipedia.org/wiki/Zachary_Taylor,04/03/1849,09/07/1850,Whig,Louisiana
-13,Millard Fillmore,http://en.wikipedia.org/wiki/Millard_Fillmore,09/07/1850,04/03/1853,Whig,New York
-14,Franklin Pierce,http://en.wikipedia.org/wiki/Franklin_Pierce,04/03/1853,04/03/1857,Democratic,New Hampshire
-15,James Buchanan,http://en.wikipedia.org/wiki/James_Buchanan,04/03/1857,04/03/1861,Democratic,Pennsylvania
-16,Abraham Lincoln,http://en.wikipedia.org/wiki/Abraham_Lincoln,04/03/1861,15/04/1865,Republican/National Union,Illinois
-17,Andrew Johnson,http://en.wikipedia.org/wiki/Andrew_Johnson,15/04/1865,04/03/1869,Democratic/National Union,Tennessee
-18,Ulysses S. Grant,http://en.wikipedia.org/wiki/Ulysses_S._Grant,04/03/1869,04/03/1877,Republican,Ohio
-19,Rutherford B. Hayes,http://en.wikipedia.org/wiki/Rutherford_B._Hayes,04/03/1877,04/03/1881,Republican,Ohio
-20,James A. Garfield,http://en.wikipedia.org/wiki/James_A._Garfield,04/03/1881,19/09/1881,Republican,Ohio
-21,Chester A. Arthur,http://en.wikipedia.org/wiki/Chester_A._Arthur,19/09/1881,04/03/1885,Republican,New York
-22,Grover Cleveland,http://en.wikipedia.org/wiki/Grover_Cleveland,04/03/1885,04/03/1889,Democratic,New York
-23,Benjamin Harrison,http://en.wikipedia.org/wiki/Benjamin_Harrison,04/03/1889,04/03/1893,Republican,Indiana
-24,Grover Cleveland (2nd term),http://en.wikipedia.org/wiki/Grover_Cleveland,04/03/1893,04/03/1897,Democratic,New York
-25,William McKinley,http://en.wikipedia.org/wiki/William_McKinley,04/03/1897,14/09/1901,Republican,Ohio
-26,Theodore Roosevelt,http://en.wikipedia.org/wiki/Theodore_Roosevelt,14/09/1901,04/03/1909,Republican,New York
-27,William Howard Taft,http://en.wikipedia.org/wiki/William_Howard_Taft,04/03/1909,04/03/1913,Republican,Ohio
-28,Woodrow Wilson,http://en.wikipedia.org/wiki/Woodrow_Wilson,04/03/1913,04/03/1921,Democratic,New Jersey
-29,Warren G. Harding,http://en.wikipedia.org/wiki/Warren_G._Harding,04/03/1921,02/08/1923,Republican,Ohio
-30,Calvin Coolidge,http://en.wikipedia.org/wiki/Calvin_Coolidge,02/08/1923,04/03/1929,Republican,Massachusetts
-31,Herbert Hoover,http://en.wikipedia.org/wiki/Herbert_Hoover,04/03/1929,04/03/1933,Republican,Iowa
-32,Franklin D. Roosevelt,http://en.wikipedia.org/wiki/Franklin_D._Roosevelt,04/03/1933,12/04/1945,Democratic,New York
-33,Harry S. Truman,http://en.wikipedia.org/wiki/Harry_S._Truman,12/04/1945,20/01/1953,Democratic,Missouri
-34,Dwight D. Eisenhower,http://en.wikipedia.org/wiki/Dwight_D._Eisenhower,20/01/1953,20/01/1961,Republican,Texas
-35,John F. Kennedy,http://en.wikipedia.org/wiki/John_F._Kennedy,20/01/1961,22/11/1963,Democratic,Massachusetts
-36,Lyndon B. Johnson,http://en.wikipedia.org/wiki/Lyndon_B._Johnson,22/11/1963,20/01/1969,Democratic,Texas
-37,Richard Nixon,http://en.wikipedia.org/wiki/Richard_Nixon,20/01/1969,09/08/1974,Republican,California
-38,Gerald Ford,http://en.wikipedia.org/wiki/Gerald_Ford,09/08/1974,20/01/1977,Republican,Michigan
-39,Jimmy Carter,http://en.wikipedia.org/wiki/Jimmy_Carter,20/01/1977,20/01/1981,Democratic,Georgia
-40,Ronald Reagan,http://en.wikipedia.org/wiki/Ronald_Reagan,20/01/1981,20/01/1989,Republican,California
-41,George H. W. Bush,http://en.wikipedia.org/wiki/George_H._W._Bush,20/01/1989,20/01/1993,Republican,Texas
-42,Bill Clinton,http://en.wikipedia.org/wiki/Bill_Clinton,20/01/1993,20/01/2001,Democratic,Arkansas
-43,George W. Bush,http://en.wikipedia.org/wiki/George_W._Bush,20/01/2001,20/01/2009,Republican,Texas
-44,Barack Obama,http://en.wikipedia.org/wiki/Barack_Obama,20/01/2009,Incumbent,  Democratic  ,Illinois
diff --git a/benchmarks/presidents_with_header.csv b/benchmarks/presidents_with_header.csv
deleted file mode 100644
--- a/benchmarks/presidents_with_header.csv
+++ /dev/null
@@ -1,45 +0,0 @@
-Presidency,President,Wikipedia Entry,Took office,Left office,Party,Home State
-1,George Washington,http://en.wikipedia.org/wiki/George_Washington,30/04/1789,04/03/1797,Independent,Virginia
-2,John Adams,http://en.wikipedia.org/wiki/John_Adams,04/03/1797,04/03/1801,Federalist,Massachusetts
-3,Thomas Jefferson,http://en.wikipedia.org/wiki/Thomas_Jefferson,04/03/1801,04/03/1809,Democratic-Republican,Virginia
-4,James Madison,http://en.wikipedia.org/wiki/James_Madison,04/03/1809,04/03/1817,Democratic-Republican,Virginia
-5,James Monroe,http://en.wikipedia.org/wiki/James_Monroe,04/03/1817,04/03/1825,Democratic-Republican,Virginia
-6,John Quincy Adams,http://en.wikipedia.org/wiki/John_Quincy_Adams,04/03/1825,04/03/1829,Democratic-Republican/National Republican,Massachusetts
-7,Andrew Jackson,http://en.wikipedia.org/wiki/Andrew_Jackson,04/03/1829,04/03/1837,Democratic,Tennessee
-8,Martin Van Buren,http://en.wikipedia.org/wiki/Martin_Van_Buren,04/03/1837,04/03/1841,Democratic,New York
-9,William Henry Harrison,http://en.wikipedia.org/wiki/William_Henry_Harrison,04/03/1841,04/04/1841,Whig,Ohio
-10,John Tyler,http://en.wikipedia.org/wiki/John_Tyler,04/04/1841,04/03/1845,Whig,Virginia
-11,James K. Polk,http://en.wikipedia.org/wiki/James_K._Polk,04/03/1845,04/03/1849,Democratic,Tennessee
-12,Zachary Taylor,http://en.wikipedia.org/wiki/Zachary_Taylor,04/03/1849,09/07/1850,Whig,Louisiana
-13,Millard Fillmore,http://en.wikipedia.org/wiki/Millard_Fillmore,09/07/1850,04/03/1853,Whig,New York
-14,Franklin Pierce,http://en.wikipedia.org/wiki/Franklin_Pierce,04/03/1853,04/03/1857,Democratic,New Hampshire
-15,James Buchanan,http://en.wikipedia.org/wiki/James_Buchanan,04/03/1857,04/03/1861,Democratic,Pennsylvania
-16,Abraham Lincoln,http://en.wikipedia.org/wiki/Abraham_Lincoln,04/03/1861,15/04/1865,Republican/National Union,Illinois
-17,Andrew Johnson,http://en.wikipedia.org/wiki/Andrew_Johnson,15/04/1865,04/03/1869,Democratic/National Union,Tennessee
-18,Ulysses S. Grant,http://en.wikipedia.org/wiki/Ulysses_S._Grant,04/03/1869,04/03/1877,Republican,Ohio
-19,Rutherford B. Hayes,http://en.wikipedia.org/wiki/Rutherford_B._Hayes,04/03/1877,04/03/1881,Republican,Ohio
-20,James A. Garfield,http://en.wikipedia.org/wiki/James_A._Garfield,04/03/1881,19/09/1881,Republican,Ohio
-21,Chester A. Arthur,http://en.wikipedia.org/wiki/Chester_A._Arthur,19/09/1881,04/03/1885,Republican,New York
-22,Grover Cleveland,http://en.wikipedia.org/wiki/Grover_Cleveland,04/03/1885,04/03/1889,Democratic,New York
-23,Benjamin Harrison,http://en.wikipedia.org/wiki/Benjamin_Harrison,04/03/1889,04/03/1893,Republican,Indiana
-24,Grover Cleveland (2nd term),http://en.wikipedia.org/wiki/Grover_Cleveland,04/03/1893,04/03/1897,Democratic,New York
-25,William McKinley,http://en.wikipedia.org/wiki/William_McKinley,04/03/1897,14/09/1901,Republican,Ohio
-26,Theodore Roosevelt,http://en.wikipedia.org/wiki/Theodore_Roosevelt,14/09/1901,04/03/1909,Republican,New York
-27,William Howard Taft,http://en.wikipedia.org/wiki/William_Howard_Taft,04/03/1909,04/03/1913,Republican,Ohio
-28,Woodrow Wilson,http://en.wikipedia.org/wiki/Woodrow_Wilson,04/03/1913,04/03/1921,Democratic,New Jersey
-29,Warren G. Harding,http://en.wikipedia.org/wiki/Warren_G._Harding,04/03/1921,02/08/1923,Republican,Ohio
-30,Calvin Coolidge,http://en.wikipedia.org/wiki/Calvin_Coolidge,02/08/1923,04/03/1929,Republican,Massachusetts
-31,Herbert Hoover,http://en.wikipedia.org/wiki/Herbert_Hoover,04/03/1929,04/03/1933,Republican,Iowa
-32,Franklin D. Roosevelt,http://en.wikipedia.org/wiki/Franklin_D._Roosevelt,04/03/1933,12/04/1945,Democratic,New York
-33,Harry S. Truman,http://en.wikipedia.org/wiki/Harry_S._Truman,12/04/1945,20/01/1953,Democratic,Missouri
-34,Dwight D. Eisenhower,http://en.wikipedia.org/wiki/Dwight_D._Eisenhower,20/01/1953,20/01/1961,Republican,Texas
-35,John F. Kennedy,http://en.wikipedia.org/wiki/John_F._Kennedy,20/01/1961,22/11/1963,Democratic,Massachusetts
-36,Lyndon B. Johnson,http://en.wikipedia.org/wiki/Lyndon_B._Johnson,22/11/1963,20/01/1969,Democratic,Texas
-37,Richard Nixon,http://en.wikipedia.org/wiki/Richard_Nixon,20/01/1969,09/08/1974,Republican,California
-38,Gerald Ford,http://en.wikipedia.org/wiki/Gerald_Ford,09/08/1974,20/01/1977,Republican,Michigan
-39,Jimmy Carter,http://en.wikipedia.org/wiki/Jimmy_Carter,20/01/1977,20/01/1981,Democratic,Georgia
-40,Ronald Reagan,http://en.wikipedia.org/wiki/Ronald_Reagan,20/01/1981,20/01/1989,Republican,California
-41,George H. W. Bush,http://en.wikipedia.org/wiki/George_H._W._Bush,20/01/1989,20/01/1993,Republican,Texas
-42,Bill Clinton,http://en.wikipedia.org/wiki/Bill_Clinton,20/01/1993,20/01/2001,Democratic,Arkansas
-43,George W. Bush,http://en.wikipedia.org/wiki/George_W._Bush,20/01/2001,20/01/2009,Republican,Texas
-44,Barack Obama,http://en.wikipedia.org/wiki/Barack_Obama,20/01/2009,Incumbent,  Democratic  ,Illinois
diff --git a/cassava.cabal b/cassava.cabal
--- a/cassava.cabal
+++ b/cassava.cabal
@@ -1,5 +1,5 @@
 Name:                cassava
-Version:             0.4.5.1
+Version:             0.5.0.0
 Synopsis:            A CSV parsing and encoding library
 Description:
   A CSV parsing and encoding library optimized for ease of use and high
@@ -16,11 +16,15 @@
 Category:            Text, Web, CSV
 Build-type:          Simple
 Cabal-version:       >=1.10
-Extra-source-files:  benchmarks/*.csv,
-                     examples/*.hs,
+Extra-source-files:  examples/*.hs,
                      CHANGES.md
-Tested-with:         GHC ==8.0.1, GHC ==7.10.3, GHC ==7.8.4, GHC ==7.6.3, GHC ==7.4.2
+Tested-with:         GHC ==8.2.1, GHC ==8.0.2, GHC ==8.0.1, GHC ==7.10.3, GHC ==7.8.4, GHC ==7.6.3, GHC ==7.4.2
 
+----------------------------------------------------------------------------
+
+flag pre-bytestring-0-10-4
+  description: bytestring < 0.10.4
+
 Library
   default-language: Haskell2010
   other-extensions:
@@ -60,90 +64,74 @@
     Data.Csv.Util
 
   Build-depends:
-    array < 0.6,
+    array >= 0.4 && < 0.6,
     attoparsec >= 0.10.2 && < 0.14,
     base >= 4.5 && < 5,
-    blaze-builder < 0.5,
-    bytestring < 0.11,
-    containers < 0.6,
+    bytestring >= 0.9.2 && < 0.11,
+    containers >= 0.4.2 && < 0.6,
     deepseq >= 1.1 && < 1.5,
     hashable < 1.3,
     text < 1.3,
     unordered-containers < 0.3,
-    vector < 0.12
+    vector >= 0.8 && < 0.13,
+    Only >= 0.1 && < 0.1.1
 
+  if flag(pre-bytestring-0-10-4)
+    build-depends: bytestring <  0.10.4
+                 , bytestring-builder >= 0.10.8 && < 0.11
+  else
+    build-depends: bytestring >= 0.10.4
+                 , text-short == 0.1.*
+
   -- GHC.Generics lived in `ghc-prim` for GHC 7.2 & GHC 7.4 only
   if impl(ghc < 7.6)
     build-depends: ghc-prim == 0.2.*
 
+  -- https://ghc.haskell.org/trac/ghc/wiki/Migration/8.0#Recommendationsforforward-compatibility
+  if impl(ghc >= 8.0)
+    ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances
+  else
+    -- provide/emulate `Control.Monad.Fail` and `Data.Semigroups` API for pre-GHC8
+    build-depends: fail == 4.9.*, semigroups == 0.18.*
+
+  if impl(ghc >= 8.2)
+    ghc-options: -Wcpp-undef
+
   ghc-options: -Wall -O2
 
+----------------------------------------------------------------------------
+
 Test-suite unit-tests
   default-language: Haskell2010
 
   Type: exitcode-stdio-1.0
   Main-is: UnitTests.hs
-  Build-depends:
-    attoparsec,
-    base >= 4.5,
-    bytestring,
-    cassava,
-    hashable < 1.3,
-    HUnit,
-    QuickCheck >= 2.0,
-    test-framework,
-    test-framework-hunit,
-    test-framework-quickcheck2,
-    text,
-    unordered-containers,
-    vector
+  -- dependencies with version constraints inherited via lib:cassava
+  Build-depends: attoparsec
+               , base
+               , bytestring
+               , cassava
+               , hashable
+               , text
+               , unordered-containers
+               , vector
+  -- extra dependencies not already used by lib:cassava
+  build-depends: HUnit < 1.7
+               , QuickCheck == 2.10.*
+               , test-framework == 0.8.*
+               , test-framework-hunit == 0.3.*
+               , test-framework-quickcheck2 == 0.3.*
 
   hs-source-dirs: tests
-  ghc-options: -Wall
 
-Benchmark benchmarks
-  default-language: Haskell2010
-
-  Type: exitcode-stdio-1.0
-  Main-is: Benchmarks.hs
-
-  Other-modules:
-    Data.Csv
-    Data.Csv.Conversion
-    Data.Csv.Conversion.Internal
-    Data.Csv.Encoding
-    Data.Csv.Incremental
-    Data.Csv.Parser
-    Data.Csv.Streaming
-    Data.Csv.Types
-    Data.Csv.Util
-
-  Build-depends:
-    array < 0.6,
-    attoparsec >= 0.10.2 && < 0.14,
-    base >= 4.5 && < 5,
-    blaze-builder < 0.5,
-    bytestring < 0.11,
-    containers < 0.6,
-    criterion >= 1.0,
-    deepseq < 1.5,
-    hashable < 1.3,
-    lazy-csv >= 0.5,
-    text < 1.3,
-    text,
-    unordered-containers < 0.3,
-    vector < 0.12
-
-  -- GHC.Generics lived in `ghc-prim` for GHC 7.2 & GHC 7.4 only
-  if impl(ghc < 7.6)
-    build-depends: ghc-prim == 0.2.*
-
-  ghc-options: -Wall -O2
+  -- https://ghc.haskell.org/trac/ghc/wiki/Migration/8.0#Recommendationsforforward-compatibility
+  if impl(ghc >= 8.0)
+    ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances
+  else
+    -- provide/emulate `Control.Monad.Fail` and `Data.Semigroups` API for pre-GHC8
+    build-depends: fail == 4.9.*, semigroups == 0.18.*
 
-  -- We cannot depend on the library directly as that creates a
-  -- dependency cycle.
-  hs-source-dirs: . benchmarks
+  if impl(ghc >= 8.2)
+    ghc-options: -Wcpp-undef
 
-source-repository head
-  type:     git
-  location: https://github.com/hvr/cassava.git
+  ghc-options: -Wall
diff --git a/tests/UnitTests.hs b/tests/UnitTests.hs
--- a/tests/UnitTests.hs
+++ b/tests/UnitTests.hs
@@ -111,7 +111,7 @@
       , ("quoted",       [["\"abc\""]],      "\"\"\"abc\"\"\"\r\n")
       , ("quote",        [["a\"b"]],         "\"a\"\"b\"\r\n")
       , ("quotedQuote",  [["\"a\"b\""]],     "\"\"\"a\"\"b\"\"\"\r\n")
-      , ("leadingSpace", [[" abc"]],         "\" abc\"\r\n")
+      , ("leadingSpace", [[" abc"]],         " abc\r\n")
       , ("comma",        [["abc,def"]],      "\"abc,def\"\r\n")
       , ("twoFields",    [["abc","def"]],    "abc,def\r\n")
       , ("twoRecords",   [["abc"], ["def"]], "abc\r\ndef\r\n")
@@ -370,6 +370,7 @@
   [
     testGroup "Records instances"
     [ testCase "foldr Foldable" (expected @=? F.foldr (:) [] input)
+    , testCase "foldl' Foldable" (expected @=? F.foldl' (flip (:)) [] input)
     ]
   ]
   where
