csv-conduit 0.7.3.0 → 1.0.0.1
raw patch · 8 files changed
+125/−105 lines, 8 filesdep −ghc-primdep −mmorphdep −monad-controlnew-uploaderPVP ok
version bump matches the API change (PVP)
Dependencies removed: ghc-prim, mmorph, monad-control, mtl, semigroups, unordered-containers
API changes (from Hackage documentation)
- Data.CSV.Conduit: [csvQuoteChar] :: CSVSettings -> !Maybe Char
- Data.CSV.Conduit: instance (Data.CSV.Conduit.Conversion.FromNamedRecord a, Data.CSV.Conduit.Conversion.ToNamedRecord a, Data.CSV.Conduit.CSV s (Data.CSV.Conduit.Types.MapRow Data.ByteString.Internal.ByteString)) => Data.CSV.Conduit.CSV s (Data.CSV.Conduit.Conversion.Named a)
- Data.CSV.Conduit: instance (Data.CSV.Conduit.Conversion.FromNamedRecordOrdered a, Data.CSV.Conduit.Conversion.ToNamedRecordOrdered a, Data.CSV.Conduit.CSV s (Data.CSV.Conduit.Types.OrderedMapRow Data.ByteString.Internal.ByteString)) => Data.CSV.Conduit.CSV s (Data.CSV.Conduit.Conversion.NamedOrdered a)
- Data.CSV.Conduit: instance Data.CSV.Conduit.CSV Data.ByteString.Internal.ByteString (Data.CSV.Conduit.Types.Row Data.ByteString.Internal.ByteString)
- Data.CSV.Conduit: instance Data.CSV.Conduit.CSV Data.ByteString.Internal.ByteString (Data.CSV.Conduit.Types.Row Data.Text.Internal.Text)
- Data.CSV.Conduit: instance Data.CSV.Conduit.CSV Data.ByteString.Internal.ByteString (Data.CSV.Conduit.Types.Row GHC.Base.String)
- Data.CSV.Conduit.Conversion: instance (Data.CSV.Conduit.Conversion.FromField a, GHC.Generics.Selector s) => Data.CSV.Conduit.Conversion.GFromRecordProd (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a)) Data.CSV.Conduit.Conversion.NamedRecord
- Data.CSV.Conduit.Conversion: instance (Data.CSV.Conduit.Conversion.GFromRecordProd a r, Data.CSV.Conduit.Conversion.GFromRecordProd b r) => Data.CSV.Conduit.Conversion.GFromRecordProd (a GHC.Generics.:*: b) r
- Data.CSV.Conduit.Conversion: instance (Data.CSV.Conduit.Conversion.GFromRecordSum a r, Data.CSV.Conduit.Conversion.GFromRecordSum b r) => Data.CSV.Conduit.Conversion.GFromRecordSum (a GHC.Generics.:+: b) r
- Data.CSV.Conduit.Conversion: instance (Data.CSV.Conduit.Conversion.GToRecord a f, Data.CSV.Conduit.Conversion.GToRecord b f) => Data.CSV.Conduit.Conversion.GToRecord (a GHC.Generics.:*: b) f
- Data.CSV.Conduit.Conversion: instance (Data.CSV.Conduit.Conversion.GToRecord a f, Data.CSV.Conduit.Conversion.GToRecord b f) => Data.CSV.Conduit.Conversion.GToRecord (a GHC.Generics.:+: b) f
- Data.CSV.Conduit.Conversion: instance (Data.CSV.Conduit.Conversion.ToField a, GHC.Generics.Selector s) => Data.CSV.Conduit.Conversion.GToRecord (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i a)) (Data.ByteString.Internal.ByteString, Data.ByteString.Internal.ByteString)
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.FromField Data.ByteString.Internal.ByteString
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.FromField GHC.Integer.Type.Integer
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.FromField a => Data.CSV.Conduit.Conversion.FromNamedRecord (Data.Map.Internal.Map Data.ByteString.Internal.ByteString a)
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.FromField a => Data.CSV.Conduit.Conversion.FromNamedRecordOrdered (Data.Map.Ordered.Internal.OMap Data.ByteString.Internal.ByteString a)
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.FromField a => Data.CSV.Conduit.Conversion.GFromRecordProd (GHC.Generics.K1 i a) Data.CSV.Conduit.Conversion.Record
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.GFromRecordProd GHC.Generics.U1 r
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.GFromRecordProd f Data.CSV.Conduit.Conversion.Record => Data.CSV.Conduit.Conversion.GFromRecordProd (GHC.Generics.M1 i n f) Data.CSV.Conduit.Conversion.Record
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.GFromRecordProd f r => Data.CSV.Conduit.Conversion.GFromRecordSum (GHC.Generics.M1 i n f) r
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.GFromRecordSum f Data.CSV.Conduit.Conversion.NamedRecord => Data.CSV.Conduit.Conversion.GFromNamedRecord (GHC.Generics.M1 i n f)
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.GFromRecordSum f Data.CSV.Conduit.Conversion.Record => Data.CSV.Conduit.Conversion.GFromRecord (GHC.Generics.M1 i n f)
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.GToRecord GHC.Generics.U1 f
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.GToRecord a Data.CSV.Conduit.Conversion.Field => Data.CSV.Conduit.Conversion.GToRecord (GHC.Generics.M1 GHC.Generics.S c a) Data.CSV.Conduit.Conversion.Field
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.GToRecord a f => Data.CSV.Conduit.Conversion.GToRecord (GHC.Generics.M1 GHC.Generics.C c a) f
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.GToRecord a f => Data.CSV.Conduit.Conversion.GToRecord (GHC.Generics.M1 GHC.Generics.D c a) f
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.ToField Data.ByteString.Internal.ByteString
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.ToField GHC.Integer.Type.Integer
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.ToField a => Data.CSV.Conduit.Conversion.GToRecord (GHC.Generics.K1 i a) Data.CSV.Conduit.Conversion.Field
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.ToField a => Data.CSV.Conduit.Conversion.ToNamedRecord (Data.Map.Internal.Map Data.ByteString.Internal.ByteString a)
- Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.ToField a => Data.CSV.Conduit.Conversion.ToNamedRecordOrdered (Data.Map.Ordered.Internal.OMap Data.ByteString.Internal.ByteString a)
- Data.CSV.Conduit.Types: [csvQuoteChar] :: CSVSettings -> !Maybe Char
- Data.CSV.Conduit.Types: instance GHC.Read.Read Data.CSV.Conduit.Types.CSVSettings
+ Data.CSV.Conduit: [csvQuoteCharAndStyle] :: CSVSettings -> !Maybe (Char, QuoteEmpty)
+ Data.CSV.Conduit: instance (Data.CSV.Conduit.Conversion.FromNamedRecord a, Data.CSV.Conduit.Conversion.ToNamedRecord a, Data.CSV.Conduit.CSV s (Data.CSV.Conduit.Types.MapRow Data.ByteString.Internal.Type.ByteString)) => Data.CSV.Conduit.CSV s (Data.CSV.Conduit.Conversion.Named a)
+ Data.CSV.Conduit: instance (Data.CSV.Conduit.Conversion.FromNamedRecordOrdered a, Data.CSV.Conduit.Conversion.ToNamedRecordOrdered a, Data.CSV.Conduit.CSV s (Data.CSV.Conduit.Types.OrderedMapRow Data.ByteString.Internal.Type.ByteString)) => Data.CSV.Conduit.CSV s (Data.CSV.Conduit.Conversion.NamedOrdered a)
+ Data.CSV.Conduit: instance Data.CSV.Conduit.CSV Data.ByteString.Internal.Type.ByteString (Data.CSV.Conduit.Types.Row Data.ByteString.Internal.Type.ByteString)
+ Data.CSV.Conduit: instance Data.CSV.Conduit.CSV Data.ByteString.Internal.Type.ByteString (Data.CSV.Conduit.Types.Row Data.Text.Internal.Text)
+ Data.CSV.Conduit: instance Data.CSV.Conduit.CSV Data.ByteString.Internal.Type.ByteString (Data.CSV.Conduit.Types.Row GHC.Base.String)
+ Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.FromField Data.ByteString.Internal.Type.ByteString
+ Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.FromField GHC.Num.Integer.Integer
+ Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.FromField a => Data.CSV.Conduit.Conversion.FromNamedRecord (Data.Map.Internal.Map Data.ByteString.Internal.Type.ByteString a)
+ Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.FromField a => Data.CSV.Conduit.Conversion.FromNamedRecordOrdered (Data.Map.Ordered.Internal.OMap Data.ByteString.Internal.Type.ByteString a)
+ Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.ToField Data.ByteString.Internal.Type.ByteString
+ Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.ToField GHC.Num.Integer.Integer
+ Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.ToField a => Data.CSV.Conduit.Conversion.ToNamedRecord (Data.Map.Internal.Map Data.ByteString.Internal.Type.ByteString a)
+ Data.CSV.Conduit.Conversion: instance Data.CSV.Conduit.Conversion.ToField a => Data.CSV.Conduit.Conversion.ToNamedRecordOrdered (Data.Map.Ordered.Internal.OMap Data.ByteString.Internal.Type.ByteString a)
+ Data.CSV.Conduit.Types: DoQuoteEmpty :: QuoteEmpty
+ Data.CSV.Conduit.Types: DontQuoteEmpty :: QuoteEmpty
+ Data.CSV.Conduit.Types: [csvQuoteCharAndStyle] :: CSVSettings -> !Maybe (Char, QuoteEmpty)
+ Data.CSV.Conduit.Types: csvQuoteChar :: CSVSettings -> Maybe Char
+ Data.CSV.Conduit.Types: data QuoteEmpty
+ Data.CSV.Conduit.Types: defDontQuoteEmptyCSVSettings :: CSVSettings
+ Data.CSV.Conduit.Types: instance GHC.Classes.Eq Data.CSV.Conduit.Types.QuoteEmpty
+ Data.CSV.Conduit.Types: instance GHC.Show.Show Data.CSV.Conduit.Types.QuoteEmpty
- Data.CSV.Conduit: CSVSettings :: !Char -> !Maybe Char -> CSVSettings
+ Data.CSV.Conduit: CSVSettings :: !Char -> !Maybe (Char, QuoteEmpty) -> CSVSettings
- Data.CSV.Conduit.Conversion: parseNamedRecord :: (FromNamedRecord a, Generic a, GFromNamedRecord (Rep a)) => NamedRecord -> Parser a
+ Data.CSV.Conduit.Conversion: parseNamedRecord :: FromNamedRecord a => NamedRecord -> Parser a
- Data.CSV.Conduit.Conversion: parseRecord :: (FromRecord a, Generic a, GFromRecord (Rep a)) => Record -> Parser a
+ Data.CSV.Conduit.Conversion: parseRecord :: FromRecord a => Record -> Parser a
- Data.CSV.Conduit.Conversion: toNamedRecord :: (ToNamedRecord a, Generic a, GToRecord (Rep a) (ByteString, ByteString)) => a -> NamedRecord
+ Data.CSV.Conduit.Conversion: toNamedRecord :: ToNamedRecord a => a -> NamedRecord
- Data.CSV.Conduit.Conversion: toRecord :: (ToRecord a, Generic a, GToRecord (Rep a) Field) => a -> Record
+ Data.CSV.Conduit.Conversion: toRecord :: ToRecord a => a -> Record
- Data.CSV.Conduit.Types: CSVSettings :: !Char -> !Maybe Char -> CSVSettings
+ Data.CSV.Conduit.Types: CSVSettings :: !Char -> !Maybe (Char, QuoteEmpty) -> CSVSettings
Files
- LICENSE +1/−0
- README.md +9/−7
- changelog.md +13/−0
- csv-conduit.cabal +65/−73
- src/Data/CSV/Conduit.hs +15/−10
- src/Data/CSV/Conduit/Conversion.hs +9/−11
- src/Data/CSV/Conduit/Types.hs +11/−3
- test/Test.hs +2/−1
LICENSE view
@@ -1,3 +1,4 @@+Copyright (c)2024, Daniel Vianna Copyright (c)2013, Ozgun Ataman Copyright (c)2012, Johan Tibell
README.md view
@@ -1,4 +1,7 @@-# README [](https://travis-ci.org/ozataman/csv-conduit)+# README+[](https://github.com/dmvianna/csv-conduit/actions)+[](https://github.com/dmvianna/csv-conduit/actions) ## CSV Files and Haskell @@ -90,9 +93,9 @@ myProcessor = CL.map reverse test :: IO ()-test = runResourceT $ - transformCSV defCSVSettings - (sourceFile "input.csv") +test = runResourceT $+ transformCSV defCSVSettings+ (sourceFile "input.csv") myProcessor (sinkFile "output.csv") ```@@ -113,11 +116,10 @@ -- Let's simply stream from a file, parse the CSV, reserialize it -- and push back into another file. test :: IO ()-test = runResourceT $ - sourceFile "test/BigFile.csv" $= +test = runResourceT $+ sourceFile "test/BigFile.csv" $= intoCSV defCSVSettings $= myProcessor $= fromCSV defCSVSettings $$ sinkFile "test/BigFileOut.csv" ```-
changelog.md view
@@ -1,3 +1,16 @@+1.0.0.1+* Removed dependencies: mmorph, monad-control, mtl,+ unordered-containers, primitive++1.0.0.0+* Removed `return` from the `Monad` instance for `Parser`, and+ transfered its definition to `pure` in the `Applicative` instance of+ `Parser`. This was necessary to support GHC 9.6.4.+* Create new API to choose whether to handle empty CSV cells as empty+ strings or NULLs.+* Added imports that were removed from `Prelude` in GHC 9.6.4.+* Bumped the default Stack resolver to LTS-22.20.+ 0.7.3.0 * Add ordered versions of named records for consistent, controllable header column ordering. [PR 44](https://github.com/ozataman/csv-conduit/pull/44) * Add support for GHC 9.0.1
csv-conduit.cabal view
@@ -1,27 +1,34 @@-Name: csv-conduit-Version: 0.7.3.0-Synopsis: A flexible, fast, conduit-based CSV parser library for Haskell.-Homepage: http://github.com/ozataman/csv-conduit-License: BSD3-License-file: LICENSE-Author: Ozgun Ataman-Maintainer: Ozgun Ataman <ozataman@gmail.com>-Category: Data, Conduit, CSV, Text-Build-type: Simple-Cabal-version: >= 1.10-Tested-with: GHC == 9.0.1, GHC == 8.10.4, GHC == 8.8.4, GHC == 8.8.3, GHC == 8.6.5, GHC == 8.4.4, GHC == 8.2.2-Description:+name: csv-conduit+version: 1.0.0.1+synopsis:+ A flexible, fast, conduit-based CSV parser library for Haskell.++homepage: http://github.com/dmvianna/csv-conduit+license: BSD3+license-file: LICENSE+author: Ozgun Ataman+maintainer: Daniel Vianna <dmvianna@gmail.com>+category: Data, Conduit, CSV, Text+build-type: Simple+cabal-version: >=1.10+tested-with:+ GHC ==8.2.2+ || ==8.4.4+ || ==8.6.5+ || ==8.8.3+ || ==8.8.4+ || ==8.10.4+ || ==9.0.1+ || ==9.6.4++description: CSV files are the de-facto standard in many situations involving data transfer, particularly when dealing with enterprise application or disparate database systems.- .- While there are a number of CSV libraries in Haskell, at the time of this project's start in 2010, there wasn't one that provided all of the following:- .- * Full flexibility in quote characters, separators, input/output . * Constant space operation@@ -32,106 +39,91 @@ . * Fast operation .- This library is an attempt to close these gaps. Please note that this library started its life based on the enumerator package and has recently been ported to work with conduits instead. In the process, it has been greatly simplified thanks to the modular nature of the conduits library.- .- Following the port to conduits, the library has also gained the ability to parameterize on the stream type and work both with ByteString and Text.- .- For more documentation and examples, check out the README at: .-- <http://github.com/ozataman/csv-conduit>+ <http://github.com/dmvianna/csv-conduit> . - extra-source-files:- README.md changelog.md+ README.md test/test.csv test/Test.hs flag lib-Werror default: False- manual: True+ manual: True library default-language: Haskell2010 exposed-modules:- Data.CSV.Conduit- Data.CSV.Conduit.Types- Data.CSV.Conduit.Conversion- Data.CSV.Conduit.Parser.ByteString- Data.CSV.Conduit.Parser.Text+ Data.CSV.Conduit+ Data.CSV.Conduit.Conversion+ Data.CSV.Conduit.Parser.ByteString+ Data.CSV.Conduit.Parser.Text+ Data.CSV.Conduit.Types+ other-modules:- Data.CSV.Conduit.Conversion.Internal- Data.CSV.Conduit.Monoid- ghc-options: -Wall -funbox-strict-fields- if flag(lib-Werror)+ Data.CSV.Conduit.Conversion.Internal+ Data.CSV.Conduit.Monoid++ ghc-options: -Wall -funbox-strict-fields++ if flag(lib-werror) ghc-options: -Werror- hs-source-dirs: src++ hs-source-dirs: src build-depends:- attoparsec >= 0.10- , base >= 4 && < 5+ array+ , attoparsec >=0.10+ , base >=4 && <5+ , blaze-builder , bytestring- , conduit >= 1.2.8+ , conduit >=1.2.8 , conduit-extra- , containers >= 0.3- , exceptions >= 0.3- , monad-control- , text+ , containers >=0.3 , data-default- , vector- , array- , blaze-builder- , unordered-containers+ , exceptions >=0.3 , ordered-containers- , transformers- , mtl- , mmorph , primitive- , resourcet >= 1.1.2.1- , semigroups-- if impl(ghc >= 7.2.1)- cpp-options: -DGENERICS- build-depends: ghc-prim >= 0.2-+ , resourcet >=1.1.2.1+ , text+ , transformers+ , vector test-suite test default-language: Haskell2010- type: exitcode-stdio-1.0- main-is: Test.hs- ghc-options: -Wall- if flag(lib-Werror)+ type: exitcode-stdio-1.0+ main-is: Test.hs+ ghc-options: -Wall -Wunused-packages++ if flag(lib-werror) ghc-options: -Werror- hs-source-dirs: test++ hs-source-dirs: test build-depends:- base >= 4 && < 5+ base >=4 && <5 , bytestring- , conduit >= 1.3.0- , containers >= 0.3+ , conduit >=1.3.0+ , containers >=0.3 , csv-conduit , directory- , vector- , HUnit >= 1.2+ , HUnit >=1.2+ , ordered-containers , test-framework , test-framework-hunit , text- , ordered-containers- , transformers- , mtl- , primitive-+ , vector source-repository head type: git
src/Data/CSV/Conduit.hs view
@@ -6,7 +6,6 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE UndecidableInstances #-} module Data.CSV.Conduit@@ -36,11 +35,12 @@ ------------------------------------------------------------------------------- import Control.Exception-import Control.Monad.Catch.Pure (CatchT)-import Control.Monad.Catch.Pure (runCatchT)-import Control.Monad.Except+import Control.Monad.Catch.Pure (runCatchT, CatchT)+import Control.Monad.IO.Class (MonadIO (liftIO)) import Control.Monad.Primitive import Control.Monad.ST+import Control.Monad.Trans.Class (MonadTrans(lift))+import Control.Monad.Trans.Except (ExceptT(..), runExceptT) import Control.Monad.Trans.Resource (MonadResource, MonadThrow, runResourceT) import Data.Attoparsec.Types (Parser)@@ -153,9 +153,12 @@ rowToStr s !r = let sep = B.pack [c2w (csvSep s)]- wrapField !f = case csvQuoteChar s of- Just !x-> (x `B8.cons` escape x f) `B8.snoc` x- _ -> f+ wrapField !f = case csvQuoteCharAndStyle s of+ Just (x, quoteEmpty) ->+ case quoteEmpty == DoQuoteEmpty || B8.length f /= 0 of+ True -> (x `B8.cons` escape x f) `B8.snoc` x+ False -> f+ Nothing -> f escape c str = B8.intercalate (B8.pack [c,c]) $ B8.split c str in B.intercalate sep . map wrapField $ r @@ -169,9 +172,11 @@ rowToStr s !r = let sep = T.pack [csvSep s]- wrapField !f = case csvQuoteChar s of- Just !x-> x `T.cons` escape x f `T.snoc` x- _ -> f+ wrapField !f = case csvQuoteCharAndStyle s of+ Just (x, quoteEmpty) -> case quoteEmpty == DoQuoteEmpty || not (T.null f) of+ True -> x `T.cons` escape x f `T.snoc` x+ False -> f+ Nothing -> f escape c str = T.intercalate (T.pack [c,c]) $ T.split (== c) str in T.intercalate sep . map wrapField $ r
src/Data/CSV/Conduit/Conversion.hs view
@@ -68,7 +68,6 @@ import qualified Data.ByteString.Char8 as B8 import qualified Data.ByteString.Lazy as L import Data.Int (Int8, Int16, Int32, Int64)-import Data.Kind (Type) import qualified Data.Map as M import qualified Data.Map.Ordered as MO import Data.Semigroup as Semigroup@@ -160,7 +159,7 @@ -- > | otherwise = mzero class FromRecord a where parseRecord :: Record -> Parser a- + #ifdef GENERICS default parseRecord :: (Generic a, GFromRecord (Rep a)) => Record -> Parser a parseRecord r = to A.<$> gparseRecord r@@ -778,8 +777,6 @@ m >>= g = Parser $ \kf ks -> let ks' a = unParser (g a) kf ks in unParser m kf ks' {-# INLINE (>>=) #-}- return a = Parser $ \_kf ks -> ks a- {-# INLINE return #-} #if MIN_VERSION_base(4,13,0) instance MonadFail Parser where@@ -794,10 +791,11 @@ {-# INLINE fmap #-} instance Applicative Parser where- pure = return- {-# INLINE pure #-}+ (<*>) = apP {-# INLINE (<*>) #-}+ pure a = Parser $ \_kf ks -> ks a+ {-# INLINE pure #-} instance Alternative Parser where empty = fail "empty"@@ -842,9 +840,9 @@ gparseRecord :: Record -> Parser (f p) instance GFromRecordSum f Record => GFromRecord (M1 i n f) where- gparseRecord v = + gparseRecord v = case (IM.lookup n gparseRecordSum) of- Nothing -> lengthMismatch n v + Nothing -> lengthMismatch n v Just p -> M1 <$> p v where n = V.length v@@ -853,15 +851,15 @@ gparseNamedRecord :: NamedRecord -> Parser (f p) instance GFromRecordSum f NamedRecord => GFromNamedRecord (M1 i n f) where- gparseNamedRecord v = + gparseNamedRecord v = foldr (\f p -> p <|> M1 <$> f v) empty (IM.elems gparseRecordSum) class GFromRecordSum f r where gparseRecordSum :: IM.IntMap (r -> Parser (f p)) instance (GFromRecordSum a r, GFromRecordSum b r) => GFromRecordSum (a :+: b) r where- gparseRecordSum = - IM.unionWith (\a b r -> a r <|> b r) + gparseRecordSum =+ IM.unionWith (\a b r -> a r <|> b r) (fmap (L1 <$>) <$> gparseRecordSum) (fmap (R1 <$>) <$> gparseRecordSum)
src/Data/CSV/Conduit/Types.hs view
@@ -9,6 +9,7 @@ import qualified Data.Map.Ordered as MO ------------------------------------------------------------------------------- +data QuoteEmpty = DoQuoteEmpty | DontQuoteEmpty deriving (Show, Eq) ------------------------------------------------------------------------------- -- | Settings for a CSV file. This library is intended to be flexible@@ -22,10 +23,12 @@ -- | Quote character that may sometimes be present around fields. -- If 'Nothing' is given, the library will never expect quotation -- even if it is present.- , csvQuoteChar :: !(Maybe Char)- } deriving (Read, Show, Eq)+ , csvQuoteCharAndStyle :: !(Maybe (Char, QuoteEmpty))+ } deriving (Show, Eq) +csvQuoteChar :: CSVSettings -> Maybe Char+csvQuoteChar = (fst <$>) . csvQuoteCharAndStyle ------------------------------------------------------------------------------- -- | Default settings for a CSV file.@@ -36,9 +39,14 @@ defCSVSettings :: CSVSettings defCSVSettings = CSVSettings { csvSep = ','- , csvQuoteChar = Just '"'+ , csvQuoteCharAndStyle = Just ('"', DoQuoteEmpty) } +defDontQuoteEmptyCSVSettings :: CSVSettings+defDontQuoteEmptyCSVSettings = CSVSettings+ { csvSep = ','+ , csvQuoteCharAndStyle = Just ('"', DontQuoteEmpty)+ } instance Default CSVSettings where def = defCSVSettings
test/Test.hs view
@@ -9,6 +9,7 @@ import qualified Data.ByteString.Char8 as B import Data.CSV.Conduit import Data.CSV.Conduit.Conversion+import Data.CSV.Conduit.Types import qualified Data.Map as Map import qualified Data.Map.Ordered as OMap import Data.Monoid as M@@ -106,7 +107,7 @@ pairs = [("b", "bval"), ("a", "aval")] csvSettings :: CSVSettings-csvSettings = defCSVSettings {csvQuoteChar = Just '`'}+csvSettings = defCSVSettings {csvQuoteCharAndStyle = Just ('`', DontQuoteEmpty)} testFile1, testFile2 :: FilePath testFile1 = "test/test.csv"