csv-conduit-0.6.7: A flexible, fast, conduit-based CSV parser library for Haskell.

CopyrightOzgun Ataman Johan Tibell
LicenseBSD3
MaintainerOzgun Ataman <ozataman@gmail.com>
Stabilityexperimental
Safe HaskellNone
LanguageHaskell98

Data.CSV.Conduit.Conversion

Contents

Description

This module has been shamelessly taken from Johan Tibell's nicely put together cassava package, which itself borrows the approach from Bryan OSullivans widely used aeson package.

We make the necessary adjustments and some simplifications here to bolt this parsing interface onto our underlying CSV typeclass.

Synopsis

Type conversion

newtype Only a #

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.

Constructors

Only 

Fields

Instances

Eq a => Eq (Only a) # 

Methods

(==) :: Only a -> Only a -> Bool #

(/=) :: Only a -> Only a -> Bool #

Ord a => Ord (Only a) # 

Methods

compare :: Only a -> Only a -> Ordering #

(<) :: Only a -> Only a -> Bool #

(<=) :: Only a -> Only a -> Bool #

(>) :: Only a -> Only a -> Bool #

(>=) :: Only a -> Only a -> Bool #

max :: Only a -> Only a -> Only a #

min :: Only a -> Only a -> Only a #

Read a => Read (Only a) # 
Show a => Show (Only a) # 

Methods

showsPrec :: Int -> Only a -> ShowS #

show :: Only a -> String #

showList :: [Only a] -> ShowS #

ToField a => ToRecord (Only a) # 

Methods

toRecord :: Only a -> Record #

FromField a => FromRecord (Only a) # 

Methods

parseRecord :: Record -> Parser (Only a) #

newtype Named a #

A wrapper around custom haskell types that can directly be converted/parsed from an incoming CSV stream.

We define this wrapper to stop GHC from complaining about overlapping instances. Just use getNamed to get your object out of the wrapper.

Constructors

Named 

Fields

Instances

(FromNamedRecord a, ToNamedRecord a, CSV s (MapRow ByteString)) => CSV s (Named a) #

Conversion of stream directly to/from a custom complex haskell type.

Methods

rowToStr :: CSVSettings -> Named a -> s #

intoCSV :: MonadThrow m => CSVSettings -> Conduit s m (Named a) #

fromCSV :: Monad m => CSVSettings -> Conduit (Named a) m s #

Eq a => Eq (Named a) # 

Methods

(==) :: Named a -> Named a -> Bool #

(/=) :: Named a -> Named a -> Bool #

Ord a => Ord (Named a) # 

Methods

compare :: Named a -> Named a -> Ordering #

(<) :: Named a -> Named a -> Bool #

(<=) :: Named a -> Named a -> Bool #

(>) :: Named a -> Named a -> Bool #

(>=) :: Named a -> Named a -> Bool #

max :: Named a -> Named a -> Named a #

min :: Named a -> Named a -> Named a #

Read a => Read (Named a) # 
Show a => Show (Named a) # 

Methods

showsPrec :: Int -> Named a -> ShowS #

show :: Named a -> String #

showList :: [Named a] -> ShowS #

type Record = Vector ByteString #

A record corresponds to a single line in a CSV file.

type NamedRecord = Map ByteString ByteString #

A shorthand for the ByteString case of MapRow

class FromRecord a where #

A type that can be converted from a single CSV record, with the possibility of failure.

When writing an instance, use empty, mzero, or fail to make a conversion fail, e.g. if a Record has the wrong number of columns.

Given this example data:

John,56
Jane,55

here's an example type and instance:

data Person = Person { name :: !Text, age :: !Int }

instance FromRecord Person where
    parseRecord v
        | length v == 2 = Person <$>
                          v .! 0 <*>
                          v .! 1
        | otherwise     = mzero

Methods

parseRecord :: Record -> Parser a #

parseRecord :: (Generic a, GFromRecord (Rep a)) => Record -> Parser a #

Instances

FromField a => FromRecord [a] # 

Methods

parseRecord :: Record -> Parser [a] #

FromField a => FromRecord (Vector a) # 

Methods

parseRecord :: Record -> Parser (Vector a) #

(FromField a, Unbox a) => FromRecord (Vector a) # 

Methods

parseRecord :: Record -> Parser (Vector a) #

FromField a => FromRecord (Only a) # 

Methods

parseRecord :: Record -> Parser (Only a) #

(FromField a, FromField b) => FromRecord (a, b) # 

Methods

parseRecord :: Record -> Parser (a, b) #

(FromField a, FromField b, FromField c) => FromRecord (a, b, c) # 

Methods

parseRecord :: Record -> Parser (a, b, c) #

(FromField a, FromField b, FromField c, FromField d) => FromRecord (a, b, c, d) # 

Methods

parseRecord :: Record -> Parser (a, b, c, d) #

(FromField a, FromField b, FromField c, FromField d, FromField e) => FromRecord (a, b, c, d, e) # 

Methods

parseRecord :: Record -> Parser (a, b, c, d, e) #

(FromField a, FromField b, FromField c, FromField d, FromField e, FromField f) => FromRecord (a, b, c, d, e, f) # 

Methods

parseRecord :: Record -> Parser (a, b, c, d, e, f) #

(FromField a, FromField b, FromField c, FromField d, FromField e, FromField f, FromField g) => FromRecord (a, b, c, d, e, f, g) # 

Methods

parseRecord :: Record -> Parser (a, b, c, d, e, f, g) #

class FromNamedRecord a where #

A type that can be converted from a single CSV record, with the possibility of failure.

When writing an instance, use empty, mzero, or fail to make a conversion fail, e.g. if a Record has the wrong number of columns.

Given this example data:

name,age
John,56
Jane,55

here's an example type and instance:

{-# LANGUAGE OverloadedStrings #-}

data Person = Person { name :: !Text, age :: !Int }

instance FromRecord Person where
    parseNamedRecord m = Person <$>
                         m .: "name" <*>
                         m .: "age"

Note the use of the OverloadedStrings language extension which enables ByteString values to be written as string literals.

Methods

parseNamedRecord :: NamedRecord -> Parser a #

parseNamedRecord :: (Generic a, GFromNamedRecord (Rep a)) => NamedRecord -> Parser a #

class ToNamedRecord a where #

A type that can be converted to a single CSV record.

An example type and instance:

data Person = Person { name :: !Text, age :: !Int }

instance ToRecord Person where
    toNamedRecord (Person name age) = namedRecord [
        "name" .= name, "age" .= age]

Methods

toNamedRecord :: a -> NamedRecord #

toNamedRecord :: (Generic a, GToRecord (Rep a) (ByteString, ByteString)) => a -> NamedRecord #

class FromField a where #

A type that can be converted from a single CSV field, with the possibility of failure.

When writing an instance, use empty, mzero, or fail to make a conversion fail, e.g. if a Field can't be converted to the given type.

Example type and instance:

{-# LANGUAGE OverloadedStrings #-}

data Color = Red | Green | Blue

instance FromField Color where
    parseField s
        | s == "R"  = pure Red
        | s == "G"  = pure Green
        | s == "B"  = pure Blue
        | otherwise = mzero

Minimal complete definition

parseField

Methods

parseField :: Field -> Parser a #

Instances

FromField Char #

Assumes UTF-8 encoding.

FromField Double #

Accepts same syntax as rational.

FromField Float #

Accepts same syntax as rational.

FromField Int #

Accepts a signed decimal number.

Methods

parseField :: Field -> Parser Int #

FromField Int8 #

Accepts a signed decimal number.

FromField Int16 #

Accepts a signed decimal number.

FromField Int32 #

Accepts a signed decimal number.

FromField Int64 #

Accepts a signed decimal number.

FromField Integer #

Accepts a signed decimal number.

FromField Word #

Accepts an unsigned decimal number.

FromField Word8 #

Accepts an unsigned decimal number.

FromField Word16 #

Accepts an unsigned decimal number.

FromField Word32 #

Accepts an unsigned decimal number.

FromField Word64 #

Accepts an unsigned decimal number.

FromField () #

Ignores the Field. Always succeeds.

Methods

parseField :: Field -> Parser () #

FromField ByteString # 
FromField ByteString # 
FromField Text #

Assumes UTF-8 encoding. Fails on invalid byte sequences.

FromField Text #

Assumes UTF-8 encoding. Fails on invalid byte sequences.

FromField [Char] #

Assumes UTF-8 encoding. Fails on invalid byte sequences.

Methods

parseField :: Field -> Parser [Char] #

FromField a => FromField (Maybe a) #

Nothing if the Field is empty, Just otherwise.

Methods

parseField :: Field -> Parser (Maybe a) #

class ToRecord a where #

A type that can be converted to a single CSV record.

An example type and instance:

data Person = Person { name :: !Text, age :: !Int }

instance ToRecord Person where
    toRecord (Person name age) = record [
        toField name, toField age]

Outputs data on this form:

John,56
Jane,55

Methods

toRecord :: a -> Record #

toRecord :: (Generic a, GToRecord (Rep a) Field) => a -> Record #

Instances

ToField a => ToRecord [a] # 

Methods

toRecord :: [a] -> Record #

ToField a => ToRecord (Vector a) # 

Methods

toRecord :: Vector a -> Record #

(ToField a, Unbox a) => ToRecord (Vector a) # 

Methods

toRecord :: Vector a -> Record #

ToField a => ToRecord (Only a) # 

Methods

toRecord :: Only a -> Record #

(ToField a, ToField b) => ToRecord (a, b) # 

Methods

toRecord :: (a, b) -> Record #

(ToField a, ToField b, ToField c) => ToRecord (a, b, c) # 

Methods

toRecord :: (a, b, c) -> Record #

(ToField a, ToField b, ToField c, ToField d) => ToRecord (a, b, c, d) # 

Methods

toRecord :: (a, b, c, d) -> Record #

(ToField a, ToField b, ToField c, ToField d, ToField e) => ToRecord (a, b, c, d, e) # 

Methods

toRecord :: (a, b, c, d, e) -> Record #

(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f) => ToRecord (a, b, c, d, e, f) # 

Methods

toRecord :: (a, b, c, d, e, f) -> Record #

(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g) => ToRecord (a, b, c, d, e, f, g) # 

Methods

toRecord :: (a, b, c, d, e, f, g) -> Record #

class ToField a where #

A type that can be converted to a single CSV field.

Example type and instance:

{-# LANGUAGE OverloadedStrings #-}

data Color = Red | Green | Blue

instance ToField Color where
    toField Red   = "R"
    toField Green = "G"
    toField Blue  = "B"

Minimal complete definition

toField

Methods

toField :: a -> Field #

Instances

ToField Char #

Uses UTF-8 encoding.

Methods

toField :: Char -> Field #

ToField Double #

Uses decimal notation or scientific notation, depending on the number.

Methods

toField :: Double -> Field #

ToField Float #

Uses decimal notation or scientific notation, depending on the number.

Methods

toField :: Float -> Field #

ToField Int #

Uses decimal encoding with optional sign.

Methods

toField :: Int -> Field #

ToField Int8 #

Uses decimal encoding with optional sign.

Methods

toField :: Int8 -> Field #

ToField Int16 #

Uses decimal encoding with optional sign.

Methods

toField :: Int16 -> Field #

ToField Int32 #

Uses decimal encoding with optional sign.

Methods

toField :: Int32 -> Field #

ToField Int64 #

Uses decimal encoding with optional sign.

Methods

toField :: Int64 -> Field #

ToField Integer #

Uses decimal encoding with optional sign.

Methods

toField :: Integer -> Field #

ToField Word #

Uses decimal encoding.

Methods

toField :: Word -> Field #

ToField Word8 #

Uses decimal encoding.

Methods

toField :: Word8 -> Field #

ToField Word16 #

Uses decimal encoding.

Methods

toField :: Word16 -> Field #

ToField Word32 #

Uses decimal encoding.

Methods

toField :: Word32 -> Field #

ToField Word64 #

Uses decimal encoding.

Methods

toField :: Word64 -> Field #

ToField ByteString # 

Methods

toField :: ByteString -> Field #

ToField ByteString # 

Methods

toField :: ByteString -> Field #

ToField Text #

Uses UTF-8 encoding.

Methods

toField :: Text -> Field #

ToField Text #

Uses UTF-8 encoding.

Methods

toField :: Text -> Field #

ToField [Char] #

Uses UTF-8 encoding.

Methods

toField :: [Char] -> Field #

ToField a => ToField (Maybe a) #

Nothing is encoded as an empty field.

Methods

toField :: Maybe a -> Field #

type Field = ByteString #

A single field within a record.

Parser

data Parser a #

Conversion of a field to a value might fail e.g. if the field is malformed. This possibility is captured by the Parser type, which lets you compose several field conversions together in such a way that if any of them fail, the whole record conversion fails.

Instances

Monad Parser # 

Methods

(>>=) :: Parser a -> (a -> Parser b) -> Parser b #

(>>) :: Parser a -> Parser b -> Parser b #

return :: a -> Parser a #

fail :: String -> Parser a #

Functor Parser # 

Methods

fmap :: (a -> b) -> Parser a -> Parser b #

(<$) :: a -> Parser b -> Parser a #

Applicative Parser # 

Methods

pure :: a -> Parser a #

(<*>) :: Parser (a -> b) -> Parser a -> Parser b #

(*>) :: Parser a -> Parser b -> Parser b #

(<*) :: Parser a -> Parser b -> Parser a #

Alternative Parser # 

Methods

empty :: Parser a #

(<|>) :: Parser a -> Parser a -> Parser a #

some :: Parser a -> Parser [a] #

many :: Parser a -> Parser [a] #

MonadPlus Parser # 

Methods

mzero :: Parser a #

mplus :: Parser a -> Parser a -> Parser a #

Monoid (Parser a) # 

Methods

mempty :: Parser a #

mappend :: Parser a -> Parser a -> Parser a #

mconcat :: [Parser a] -> Parser a #

runParser :: Parser a -> Either String a #

Run a Parser, returning either Left errMsg or Right result. Forces the value in the Left or Right constructors to weak head normal form.

You most likely won't need to use this function directly, but it's included for completeness.

Accessors

index :: FromField a => Record -> Int -> Parser a #

Retrieve the nth field in the given record. The result is empty if the value cannot be converted to the desired type. Raises an exception if the index is out of bounds.

index is a simple convenience function that is equivalent to parseField (v ! idx). If you're certain that the index is not out of bounds, using unsafeIndex is somewhat faster.

(.!) :: FromField a => Record -> Int -> Parser a infixl 9 #

Alias for index.

unsafeIndex :: FromField a => Record -> Int -> Parser a #

Like index but without bounds checking.

lookup :: FromField a => NamedRecord -> ByteString -> Parser a #

Retrieve a field in the given record by name. The result is empty if the field is missing or if the value cannot be converted to the desired type.

(.:) :: FromField a => NamedRecord -> ByteString -> Parser a #

Alias for lookup.

namedField :: ToField a => ByteString -> a -> (ByteString, ByteString) #

Construct a pair from a name and a value. For use with namedRecord.

(.=) :: ToField a => ByteString -> a -> (ByteString, ByteString) #

Alias for namedField.

record :: [ByteString] -> Record #

Construct a record from a list of ByteStrings. Use toField to convert values to ByteStrings for use with record.

namedRecord :: [(ByteString, ByteString)] -> NamedRecord #

Construct a named record from a list of name-value ByteString pairs. Use .= to construct such a pair from a name and a value.