### Decoding Example Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv-Incremental.html Demonstrates how to incrementally decode CSV data from a file, handling potential errors and summing salaries. ```APIDOC ## Decoding Example ### Description This example shows how to use the incremental decoding functions to read CSV data from a file, process it in chunks, and calculate a total sum of salaries. ### Code ```haskell main :: IO () main = withFile "salaries.csv" ReadMode $ \ csvFile -> do let loop !_ (Fail _ errMsg) = putStrLn errMsg >> exitFailure loop acc (Many rs k) = loop (acc + sumSalaries rs) =<< feed k loop acc (Done rs) = putStrLn $ "Total salaries: " ++ show (sumSalaries rs + acc) feed k = do isEof <- hIsEOF csvFile if isEof then return $ k B.empty else k `fmap` B.hGetSome csvFile 4096 loop 0 (decode NoHeader) where sumSalaries rs = sum [salary | Right (_ :: String, salary :: Int) <- rs] ``` ``` -------------------------------- ### Encoding Example Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv-Incremental.html Illustrates how to incrementally encode a list of 'Person' records into CSV format using named fields. ```APIDOC ## Encoding Example ### Description This example demonstrates how to encode a list of custom data types into CSV format using named records and default ordering. ### Code ```haskell data Person = Person { name :: !String, salary :: !Int } deriving Generic instance FromNamedRecord Person instance ToNamedRecord Person instance DefaultOrdered Person persons :: [Person] persons = [Person "John" 50000, Person "Jane" 60000] main :: IO () main = putStrLn $ encodeDefaultOrderedByName (go persons) where go (x:xs) = encodeNamedRecord x <> go xs ``` ``` -------------------------------- ### Encode CSV Data with Cassava Source: https://hackage.haskell.org/package/cassava-0.5.5.0 Demonstrates a simple example of encoding a list of tuples into CSV format using the Data.Csv.encode function. Ensure the Data.Csv module is imported. ```haskell >>> **Data.Csv.encode [("John",27),("Jane",28)] **"John,27\r\nJane,28\r\n" ``` -------------------------------- ### Incremental CSV Decoding Example Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv-Incremental.html Demonstrates how to incrementally decode a CSV file, handling potential errors and accumulating results. Useful for large files where loading the entire content into memory is not feasible. ```Haskell main :: IO () main = withFile "salaries.csv" ReadMode $ \ csvFile -> do let loop !_ (Fail _ errMsg) = putStrLn errMsg >> exitFailure loop acc (Many rs k) = loop (acc + sumSalaries rs) =<< feed k loop acc (Done rs) = putStrLn $ "Total salaries: " ++ show (sumSalaries rs + acc) feed k = do isEof <- hIsEOF csvFile if isEof then return $ k B.empty else k `fmap` B.hGetSome csvFile 4096 loop 0 (decode NoHeader) where sumSalaries rs = sum [salary | Right (_ :: String, salary :: Int) <- rs] ``` -------------------------------- ### Incremental CSV Encoding Example Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv-Incremental.html Shows how to incrementally encode a list of records into CSV format. This approach is suitable for generating CSV data without holding the entire dataset in memory. ```Haskell data Person = Person { name :: !String, salary :: !Int } deriving Generic instance FromNamedRecord Person instance ToNamedRecord Person instance DefaultOrdered Person persons :: [Person] persons = [Person "John" 50000, Person "Jane" 60000] main :: IO () main = putStrLn $ encodeDefaultOrderedByName (go persons) where go (x:xs) = encodeNamedRecord x <> go xs ``` -------------------------------- ### Usage Example: Streaming CSV Decoding Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv-Streaming.html Demonstrates how to stream decode CSV data and process records. The Foldable instance skips records that fail type conversion. For different behavior, work directly with the Cons and Nil constructors. ```Haskell for_ (decode NoHeader "John,27\r\nJane,28\r\n") $ \ (name, age :: Int) -> putStrLn $ name ++ " is " ++ show age ++ " years old" ``` -------------------------------- ### Encode CSV Data Source: https://hackage.haskell.org/package/cassava-0.5.5.0/revision/0.cabal A simple example demonstrating how to encode a list of tuples into CSV format. This is useful for generating CSV output from structured data. ```haskell >>> Data.Csv.encode [("John",27),("Jane",28)] "John,27\r\nJane,28\r\n" ``` -------------------------------- ### Customizing CSV Decode Options Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv-Parser.html Create custom decode options by overriding values in `defaultDecodeOptions`. This example shows how to set the delimiter to a tab character. ```haskell myOptions = defaultDecodeOptions { decDelimiter = fromIntegral (ord '\t') } ``` -------------------------------- ### Run a CSV Parser Source: https://hackage.haskell.org/package/cassava/docs/Data-Csv.html Use `runParser` to execute a `Parser` and get either an error message or the parsed result. The result is forced into weak head normal form. ```haskell runParser :: Parser a -> Either String a ``` -------------------------------- ### Custom Hexadecimal Int Parsing with Newtype Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Define a newtype wrapper for custom field parsing, like hexadecimal integers. This example shows how to create a `Hex` newtype and an instance of `FromField` that uses a custom `parseHex` function. Pattern matching on the newtype constructor is used to specify the desired conversion. ```haskell newtype Hex = Hex Int parseHex :: ByteString -> Parser Int parseHex = ... instance FromField Hex where parseField s = Hex <$> parseHex s ``` ```haskell case decode NoHeader "0xff,0xaa\r\n0x11,0x22\r\n" of Left err -> putStrLn err Right v -> forM_ v $ \ (Hex val1, Hex val2) -> print (val1, val2) ``` -------------------------------- ### Encode Single Value with Only Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Example of encoding a single value wrapped in the `Only` newtype. ```haskell encodeSomething (Only (42::Int)) ``` -------------------------------- ### Main Function for File I/O Demonstration Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html The main function orchestrates the demonstration by first writing data to 'persons.csv' and then reading it back using the respective writeToFile and readFromFile functions. ```haskell {-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} -- from base import GHC.Generics import System.IO import System.Exit (exitFailure) -- from bytestring import Data.ByteString (ByteString, hGetSome, empty) import qualified Data.ByteString.Lazy as BL -- from cassava import Data.Csv.Incremental import Data.Csv (FromRecord, ToRecord) data Person = Person { name :: !ByteString, age :: !Int } deriving (Show, Eq, Generic) instance FromRecord Person instance ToRecord Person persons :: [Person] persons = [ Person "John Doe" 19, Person "Smith" 20 ] writeToFile :: IO () writeToFile = do BL.writeFile "persons.csv" $ encode $ foldMap encodeRecord persons feed :: (ByteString -> Parser Person) -> Handle -> IO (Parser Person) feed k csvFile = do hIsEOF csvFile >>= \case True -> return $ k empty False -> k <$> hGetSome csvFile 4096 readFromFile :: IO () readFromFile = do withFile "persons.csv" ReadMode $ \csvFile -> let loop !_ (Fail _ errMsg) = do putStrLn errMsg; exitFailure loop acc (Many rs k) = loop (acc <> rs) =<< feed k csvFile loop acc (Done rs) = print (acc <> rs) in loop [] (decode NoHeader) main :: IO () main = do writeToFile readFromFile ``` -------------------------------- ### Decode Single Value with Only Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Example of decoding a CSV row into a single value wrapped in the `Only` newtype. ```haskell xs <- decodeSomething forM_ xs $ \(Only id) -> {- ... -} ``` -------------------------------- ### FromField Instance for Color Source: https://hackage.haskell.org/package/cassava/docs/Data-Csv.html Provides a custom instance for converting CSV fields to the 'Color' data type. Uses 'mzero' to indicate a failed conversion if the field value does not match expected values. ```haskell {-# 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 ``` -------------------------------- ### FromNamedRecord Instances Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Details on instances for FromNamedRecord, enabling parsing of NamedRecords into Map and HashMap types. ```APIDOC ## FromNamedRecord Instances Instances details (FromField a, FromField b, Ord a) => FromNamedRecord (Map a b) Source #| ---|--- Instance detailsDefined in Data.Csv.Conversion MethodsparseNamedRecord :: NamedRecord -> Parser (Map a b) Source # (Eq a, FromField a, FromField b, Hashable a) => FromNamedRecord (HashMap a b) Source #| Instance detailsDefined in Data.Csv.Conversion MethodsparseNamedRecord :: NamedRecord -> Parser (HashMap a b) Source # ``` -------------------------------- ### FromField Instances for Special Types Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Instances for parsing unit type `()`, `Char`, and container types like `Identity`, `Maybe`, and `Either`. ```APIDOC ## FromField () ### Description Ignores the `Field`. Always succeeds. ### Method `parseField :: Field -> Parser ()` ## FromField Char ### Description Assumes UTF-8 encoding. ### Method `parseField :: Field -> Parser Char` ## FromField a => FromField (Identity a) ### Description Since: 0.5.2.0 ### Method `parseField :: Field -> Parser (Identity a)` ## FromField a => FromField (Maybe a) ### Description `Nothing` if the `Field` is `empty`, `Just` otherwise. ### Method `parseField :: Field -> Parser (Maybe a)` ## FromField a => FromField (Either Field a) ### Description `Left` field if conversion failed, `Right` otherwise. ### Method `parseField :: Field -> Parser (Either Field a)` ``` -------------------------------- ### Using the Only Newtype Source: https://hackage.haskell.org/package/cassava/docs/Data-Csv.html The `Only` newtype represents a single-value collection, structurally similar to `Identity`. It's useful for attaching typeclass instances where a 1-tuple is needed. Examples show encoding and decoding with `Only`. ```haskell encodeSomething (Only (42::Int)) ``` ```haskell xs <- decodeSomething forM_ xs $ \(Only id) -> {- ... -} ``` -------------------------------- ### Define ToField Instance for Custom Type Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Shows how to create a ToField instance for a custom data type, enabling its conversion to a CSV field. Requires the OverloadedStrings language extension. ```haskell {-# LANGUAGE OverloadedStrings #-} data Color = Red | Green | Blue instance ToField Color where toField Red = "R" toField Green = "G" toField Blue = "B" ``` -------------------------------- ### Define a CSV Record Type Source: https://hackage.haskell.org/package/cassava/docs/Data-Csv.html Example of defining a `Person` data type and its `ToRecord` instance to convert it into a CSV record. This demonstrates how to map Haskell data structures to CSV rows. ```haskell data Person = Person { name :: !Text, age :: !Int } instance ToRecord Person where toRecord (Person name age) = record [ toField name, toField age] ``` -------------------------------- ### FromRecord Instances for Common Types Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Demonstrates the `FromRecord` instances available for parsing CSV records into common Haskell types like tuples, lists, and vectors. Each instance relies on the `FromField` constraint for individual elements. ```APIDOC ## FromRecord Instances Cassava provides `FromRecord` instances for various types, enabling direct parsing of CSV records. ### `FromRecord (Only a)` - Requires: `FromField a` - Description: Parses a single field into a value wrapped in `Only`. - Method: `parseRecord :: Record -> Parser (Only a)` ### `FromRecord (Vector a)` - Requires: `FromField a` - Description: Parses a record into a `Vector` of elements. - Method: `parseRecord :: Record -> Parser (Vector a)` ### `FromRecord (Vector a)` (Unbox) - Requires: `FromField a`, `Unbox a` - Description: Parses a record into an unboxed `Vector` of elements for performance. - Method: `parseRecord :: Record -> Parser (Vector a)` ### `FromRecord [a]` - Requires: `FromField a` - Description: Parses a record into a list of elements. - Method: `parseRecord :: Record -> Parser [a]` ### `FromRecord (a, b)` - Requires: `FromField a`, `FromField b` - Description: Parses a record into a 2-tuple. - Method: `parseRecord :: Record -> Parser (a, b)` ### `FromRecord (a, b, c)` - Requires: `FromField a`, `FromField b`, `FromField c` - Description: Parses a record into a 3-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c)` ### `FromRecord (a, b, c, d)` - Requires: `FromField a`, `FromField b`, `FromField c`, `FromField d` - Description: Parses a record into a 4-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c, d)` ### `FromRecord (a, b, c, d, e)` - Requires: `FromField a`, `FromField b`, `FromField c`, `FromField d`, `FromField e` - Description: Parses a record into a 5-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c, d, e)` ### `FromRecord (a, b, c, d, e, f)` - Requires: `FromField a`, `FromField b`, `FromField c`, `FromField d`, `FromField e`, `FromField f` - Description: Parses a record into a 6-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c, d, e, f)` ### `FromRecord (a, b, c, d, e, f, g)` - Requires: `FromField a`, `FromField b`, `FromField c`, `FromField d`, `FromField e`, `FromField f`, `FromField g` - Description: Parses a record into a 7-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c, d, e, f, g)` ### `FromRecord (a, b, c, d, e, f, g, h)` - Requires: `FromField a`, `FromField b`, `FromField c`, `FromField d`, `FromField e`, `FromField f`, `FromField g`, `FromField h` - Description: Parses a record into an 8-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c, d, e, f, g, h)` ### `FromRecord (a, b, c, d, e, f, g, h, i)` - Requires: `FromField a`, `FromField b`, `FromField c`, `FromField d`, `FromField e`, `FromField f`, `FromField g`, `FromField h`, `FromField i` - Description: Parses a record into a 9-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c, d, e, f, g, h, i)` ### `FromRecord (a, b, c, d, e, f, g, h, i, j)` - Requires: `FromField a`, `FromField b`, `FromField c`, `FromField d`, `FromField e`, `FromField f`, `FromField g`, `FromField h`, `FromField i`, `FromField j` - Description: Parses a record into a 10-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c, d, e, f, g, h, i, j)` ### `FromRecord (a, b, c, d, e, f, g, h, i, j, k)` - Requires: `FromField a`, `FromField b`, `FromField c`, `FromField d`, `FromField e`, `FromField f`, `FromField g`, `FromField h`, `FromField i`, `FromField j`, `FromField k` - Description: Parses a record into an 11-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c, d, e, f, g, h, i, j, k)` ### `FromRecord (a, b, c, d, e, f, g, h, i, j, k, l)` - Requires: `FromField a`, `FromField b`, `FromField c`, `FromField d`, `FromField e`, `FromField f`, `FromField g`, `FromField h`, `FromField i`, `FromField j`, `FromField k`, `FromField l` - Description: Parses a record into a 12-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c, d, e, f, g, h, i, j, k, l)` ### `FromRecord (a, b, c, d, e, f, g, h, i, j, k, l, m)` - Requires: `FromField a`, `FromField b`, `FromField c`, `FromField d`, `FromField e`, `FromField f`, `FromField g`, `FromField h`, `FromField i`, `FromField j`, `FromField k`, `FromField l`, `FromField m` - Description: Parses a record into a 13-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c, d, e, f, g, h, i, j, k, l, m)` ### `FromRecord (a, b, c, d, e, f, g, h, i, j, k, l, m, n)` - Requires: `FromField a`, `FromField b`, `FromField c`, `FromField d`, `FromField e`, `FromField f`, `FromField g`, `FromField h`, `FromField i`, `FromField j`, `FromField k`, `FromField l`, `FromField m`, `FromField n` - Description: Parses a record into a 14-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c, d, e, f, g, h, i, j, k, l, m, n)` ### `FromRecord (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)` - Requires: `FromField a`, `FromField b`, `FromField c`, `FromField d`, `FromField e`, `FromField f`, `FromField g`, `FromField h`, `FromField i`, `FromField j`, `FromField k`, `FromField l`, `FromField m`, `FromField n`, `FromField o` - Description: Parses a record into a 15-tuple. - Method: `parseRecord :: Record -> Parser (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)` ``` -------------------------------- ### FromField Instances for Scientific and Rational-like Types Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Parsing for `Scientific`, `Integer`, `Natural`, `Double`, and `Float` which handle decimal numbers with varying precision and syntax. ```APIDOC ## FromField Scientific ### Description Accepts the same syntax as `rational`. Ignores whitespace. Since: 0.5.1.0 ### Method `parseField :: Field -> Parser Scientific` ## FromField Integer ### Description Accepts a signed decimal number. Ignores whitespace. ### Method `parseField :: Field -> Parser Integer` ## FromField Natural ### Description Accepts an unsigned decimal number. Ignores whitespace. Since: 0.5.1.0 ### Method `parseField :: Field -> Parser Natural` ``` -------------------------------- ### ToField Instances for Container and Wrapper Types Source: https://hackage.haskell.org/package/cassava/docs/Data-Csv.html Details the conversion of container and wrapper types to CSV Fields. Maybe types handle Nothing as an empty field, while Identity and Const are supported with type constraints. ```APIDOC ## ToField Char ### Description Uses UTF-8 encoding. ### Method toField :: Char -> Field ## ToField a => ToField (Identity a) ### Description Since: 0.5.2.0 ### Method toField :: Identity a -> Field ## ToField a => ToField (Maybe a) ### Description `Nothing` is encoded as an `empty` field. ### Method toField :: Maybe a -> Field ## ToField a => ToField (Const a b) ### Description Since: 0.5.2.0 ### Method toField :: Const a b -> Field ``` -------------------------------- ### Retrieve Record Field by Index Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Use `index` to get the nth field from a record, returning `empty` if conversion fails. It raises an exception if the index is out of bounds. This is equivalent to `parseField` applied to the record indexed by `(!)`. For performance when the index is known to be valid, `unsafeIndex` can be used. ```haskell index :: FromField a => Record -> Int -> Parser a ``` ```haskell (.!) :: FromField a => Record -> Int -> Parser a infixl 9 ``` ```haskell unsafeIndex :: FromField a => Record -> Int -> Parser a ``` -------------------------------- ### Customizing CSV Encoding with EncodeOptions Source: https://hackage.haskell.org/package/cassava/docs/Data-Csv.html Demonstrates how to create custom encoding options by overriding default values. This is useful for formats like tab-separated values. ```haskell myOptions = defaultEncodeOptions { encDelimiter = fromIntegral (ord '\t') } ``` -------------------------------- ### FromField Instances for Text and ByteString Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Details on parsing `ByteString`, `ShortByteString`, `Text`, and `ShortText` from CSV fields. These instances handle encoding and potential errors. ```APIDOC ## FromField ByteString ### Description ### Method `parseField :: Field -> Parser ByteString` ## FromField ShortByteString ### Description ### Method `parseField :: Field -> Parser ShortByteString` ## FromField Text ### Description Assumes UTF-8 encoding. Fails on invalid byte sequences. ### Method `parseField :: Field -> Parser Text` ## FromField ShortText ### Description Assumes UTF-8 encoding. Fails on invalid byte sequences. Since: 0.5.0.0 ### Method `parseField :: Field -> Parser ShortText` ## FromField [Char] ### Description Assumes UTF-8 encoding. Fails on invalid byte sequences. ### Method `parseField :: Field -> Parser [Char]` ``` -------------------------------- ### GToRecord Instances Source: https://hackage.haskell.org/package/cassava/docs/Data-Csv.html Instances for the GToRecord class, which handles converting Haskell data types into lists of fields for CSV encoding. ```APIDOC ## GToRecord Instances This section details the instances for the `GToRecord` class, which is responsible for converting Haskell data types into a list of fields suitable for CSV encoding. These instances leverage GHC generics to provide automatic derivation for various data type structures. ### `gtoRecord :: Options -> U1 p -> [f]` **Description**: Converts a unit type (`U1`) to a list of fields. ### `gtoRecord :: (GToRecord a f, GToRecord b f) => Options -> (a :*: b) p -> [f]` **Description**: Converts a product type (`a :*: b`) to a list of fields by combining the results from its constituent types. ### `gtoRecord :: (GToRecord a f, GToRecord b f) => Options -> (a :+: b) p -> [f]` **Description**: Converts a sum type (`a :+: b`) to a list of fields. The behavior depends on the specific sum type representation. ### `gtoRecord :: ToField a => Options -> K1 i a p -> [Field]` **Description**: Converts a `K1` constructor containing a `ToField` instance to a list of `Field`s. ### `gtoRecord :: GToRecord a f => Options -> M1 C c a p -> [f]` **Description**: Converts a `M1` constructor of type `C` (e.g., newtype wrapper) to a list of fields by recursing on the inner type `a`. ### `gtoRecord :: GToRecord a f => Options -> M1 D c a p -> [f]` **Description**: Converts a `M1` constructor of type `D` (e.g., data constructor wrapper) to a list of fields by recursing on the inner type `a`. ### `gtoRecord :: GToRecord a Field => Options -> M1 S c a p -> [Field]` **Description**: Converts a `M1` constructor of type `S` (e.g., record field wrapper) containing a `Field` type to a list of `Field`s. ### `gtoRecord :: (ToField a, Selector s) => Options -> M1 S s (K1 i a :: k -> Type) p -> [(ByteString, ByteString)]` **Description**: Converts a `M1` constructor of type `S` with a `Selector` and an inner `K1` containing a `ToField` instance to a list of `(ByteString, ByteString)` pairs, likely representing named fields. ``` -------------------------------- ### GToRecord Instances Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Details on instances for the GToRecord class, which handles converting generic types to CSV records. ```APIDOC ## GToRecord Instances ### Description Instances for the `GToRecord` class, which is used for converting generic types into CSV records. ### Instances - **`GToRecord (U1 :: k -> Type) f`** - Defined in `Data.Csv.Conversion` - Method: `gtoRecord :: forall (p :: k). Options -> U1 p -> [f]` - **`(GToRecord a f, GToRecord b f) => GToRecord (a :*: b :: k -> Type) f`** - Defined in `Data.Csv.Conversion` - Method: `gtoRecord :: forall (p :: k). Options -> (a :*: b) p -> [f]` - **`(GToRecord a f, GToRecord b f) => GToRecord (a :+: b :: k -> Type) f`** - Defined in `Data.Csv.Conversion` - Method: `gtoRecord :: forall (p :: k). Options -> (a :+: b) p -> [f]` - **`ToField a => GToRecord (K1 i a :: k -> Type) Field`** - Defined in `Data.Csv.Conversion` - Method: `gtoRecord :: forall (p :: k). Options -> K1 i a p -> [Field]` - **`GToRecord a f => GToRecord (M1 C c a :: k -> Type) f`** - Defined in `Data.Csv.Conversion` - Method: `gtoRecord :: forall (p :: k). Options -> M1 C c a p -> [f]` - **`GToRecord a f => GToRecord (M1 D c a :: k -> Type) f`** - Defined in `Data.Csv.Conversion` - Method: `gtoRecord :: forall (p :: k). Options -> M1 D c a p -> [f]` - **`GToRecord a Field => GToRecord (M1 S c a :: k -> Type) Field`** - Defined in `Data.Csv.Conversion` - Method: `gtoRecord :: forall (p :: k). Options -> M1 S c a p -> [Field]` - **`(ToField a, Selector s) => GToRecord (M1 S s (K1 i a :: k -> Type) :: k -> Type) (ByteString, ByteString)`** - Defined in `Data.Csv.Conversion` - Method: `gtoRecord :: forall (p :: k). Options -> M1 S s (K1 i a :: k -> Type) p -> [(ByteString, ByteString)]` ``` -------------------------------- ### Default CSV Conversion Options Source: https://hackage.haskell.org/package/cassava/docs/Data-Csv.html The default options for generic CSV conversion. These options are used when no specific modifications are needed. ```haskell defaultOptions :: Options defaultOptions = Options { fieldLabelModifier = id } ``` -------------------------------- ### runParser Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Executes a `Parser` and returns either an error message or the successfully parsed result. The result is forced to weak head normal form. ```APIDOC ## runParser ### Description Run a `Parser`, returning either `Left` errMsg or `Right` result. Forces the value in the `Left` or `Right` constructors to weak head normal form. ### Method `runParser :: Parser a -> Either String a` ``` -------------------------------- ### ToRecord Instances Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Instances for `ToRecord` that allow conversion of various tuple sizes, `Vector`s, and `Only` types into CSV `Record`s, provided the element types implement `ToField`. ```APIDOC ## ToRecord Instances Provides instances for converting various Haskell types into CSV `Record`s. ### Instances - `ToField a => ToRecord (Only a)` - `ToField a => ToRecord (Vector a)` - `(ToField a, Unbox a) => ToRecord (Vector a)` - `ToField a => ToRecord [a]` - `(ToField a, ToField b) => ToRecord (a, b)` - `(ToField a, ToField b, ToField c) => ToRecord (a, b, c)` - `(ToField a, ToField b, ToField c, ToField d) => ToRecord (a, b, c, d)` - `(ToField a, ToField b, ToField c, ToField d, ToField e) => ToRecord (a, b, c, d, e)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f) => ToRecord (a, b, c, d, e, f)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g) => ToRecord (a, b, c, d, e, f, g)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h) => ToRecord (a, b, c, d, e, f, g, h)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i) => ToRecord (a, b, c, d, e, f, g, h, i)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i, ToField j) => ToRecord (a, b, c, d, e, f, g, h, i, j)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i, ToField j, ToField k) => ToRecord (a, b, c, d, e, f, g, h, i, j, k)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i, ToField j, ToField k, ToField l) => ToRecord (a, b, c, d, e, f, g, h, i, j, k, l)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i, ToField j, ToField k, ToField l, ToField m) => ToRecord (a, b, c, d, e, f, g, h, i, j, k, l, m)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i, ToField j, ToField k, ToField l, ToField m, ToField n) => ToRecord (a, b, c, d, e, f, g, h, i, j, k, l, m, n)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i, ToField j, ToField k, ToField l, ToField m, ToField n, ToField o) => ToRecord (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)` ### Method `toRecord :: ToRecord r => r -> Record` ``` -------------------------------- ### ToRecord Instances for Various Data Types Source: https://hackage.haskell.org/package/cassava/docs/Data-Csv.html The `ToRecord` typeclass allows conversion of different data structures into a CSV `Record`. This section lists the available instances for types like `Only a`, `Vector a`, `[a]`, and tuples of varying sizes. ```APIDOC ## ToRecord Instances This section details the instances of the `ToRecord` typeclass, which enables the conversion of various Haskell data types into a CSV `Record`. ### Instances - `ToField a => ToRecord (Only a)` - `ToField a => ToRecord (Vector a)` - `(ToField a, Unbox a) => ToRecord (Vector a)` - `ToField a => ToRecord [a]` - `(ToField a, ToField b) => ToRecord (a, b)` - `(ToField a, ToField b, ToField c) => ToRecord (a, b, c)` - `(ToField a, ToField b, ToField c, ToField d) => ToRecord (a, b, c, d)` - `(ToField a, ToField b, ToField c, ToField d, ToField e) => ToRecord (a, b, c, d, e)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f) => ToRecord (a, b, c, d, e, f)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g) => ToRecord (a, b, c, d, e, f, g)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h) => ToRecord (a, b, c, d, e, f, g, h)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i) => ToRecord (a, b, c, d, e, f, g, h, i)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i, ToField j) => ToRecord (a, b, c, d, e, f, g, h, i, j)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i, ToField j, ToField k) => ToRecord (a, b, c, d, e, f, g, h, i, j, k)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i, ToField j, ToField k, ToField l) => ToRecord (a, b, c, d, e, f, g, h, i, j, k, l)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i, ToField j, ToField k, ToField l, ToField m) => ToRecord (a, b, c, d, e, f, g, h, i, j, k, l, m)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i, ToField j, ToField k, ToField l, ToField m, ToField n) => ToRecord (a, b, c, d, e, f, g, h, i, j, k, l, m, n)` - `(ToField a, ToField b, ToField c, ToField d, ToField e, ToField f, ToField g, ToField h, ToField i, ToField j, ToField k, ToField l, ToField m, ToField n, ToField o) => ToRecord (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)` ### `record` Function - `record :: [ByteString] -> Record` Constructs a `Record` from a list of `ByteString`s. Use `toField` to convert values to `ByteString`s before using this function. ``` -------------------------------- ### record Constructor Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Constructs a CSV `Record` from a list of `ByteString`s. The `toField` function can be used to convert values to `ByteString`s before using this constructor. ```APIDOC ## record Constructor Construct a record from a list of `ByteString`s. ### Usage Use `toField` to convert values to `ByteString`s for use with `record`. ```haskell record :: [ByteString] -> Record ``` ``` -------------------------------- ### Generic Record Creation Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Offers functions to create CSV records from Haskell types that are instances of the `Generic` type class. Custom `Options` can be provided to tailor the record creation process. ```APIDOC ## `genericToRecord` ### Description A configurable CSV record creator. This function applied to `defaultOptions` is used as the default for `toRecord` when the type is an instance of `Generic`. ### Method `genericToRecord :: (Generic a, GToRecord (Rep a) Field) => Options -> a -> Record` ### Since 0.5.1.0 ``` ```APIDOC ## `genericToNamedRecord` ### Description A configurable CSV named record creator. This function applied to `defaultOptions` is used as the default for `toNamedRecord` when the type is an instance of `Generic`. ### Method `genericToNamedRecord :: (Generic a, GToRecord (Rep a) (ByteString, ByteString)) => Options -> a -> NamedRecord` ### Since 0.5.1.0 ``` -------------------------------- ### Default `toRecord` Implementation Source: https://hackage.haskell.org/package/cassava/docs/Data-Csv.html A default implementation for `toRecord` that uses `Generic` and `GToRecord` to automatically derive the conversion for types that support generic programming. ```haskell default toRecord :: (Generic a, GToRecord (Rep a) Field) => a -> Record ``` -------------------------------- ### name Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv-Parser.html Parses a header name. Header names have the same format as regular `field`s. ```APIDOC ## name ### Description Parse a header name. Header names have the same format as regular `field`s. ### Arguments * **Word8**: Field delimiter ### Returns * **Parser Name** ``` -------------------------------- ### GHC Compiler Options for Cassava Source: https://hackage.haskell.org/package/cassava-0.5.5.0/revision/0.cabal Configures GHC compiler warnings based on the GHC version. Use -Wno-star-is-type for GHC >= 8.8 and -Wnoncanonical-monadfail-instances for older versions. ```yaml -Wcompat -Wcpp-undef -Wnoncanonical-monad-instances if impl(ghc >= 8.8) ghc-options: -Wno-star-is-type else ghc-options: -Wnoncanonical-monadfail-instances ``` -------------------------------- ### Running a Parser Source: https://hackage.haskell.org/package/cassava/docs/Data-Csv.html The `runParser` function executes a `Parser` and returns either an error message or the successfully parsed result. It forces the result to weak head normal form. ```APIDOC ## runParser ### Description Runs 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. ### Signature `runParser :: Parser a -> Either String a` ``` -------------------------------- ### Parser Instances Source: https://hackage.haskell.org/package/cassava-0.5.5.0/docs/Data-Csv.html Details on the various type class instances available for the Parser type, enabling advanced parsing operations. ```APIDOC ## Parser Instances ### MonadFail Parser - `fail :: String -> Parser a` ### Alternative Parser - `empty :: Parser a` - `(<|>) :: Parser a -> Parser a -> Parser a` - `some :: Parser a -> Parser [a]` - `many :: Parser a -> Parser [a]` ### Applicative Parser - `pure :: a -> Parser a` - `(<*>) :: Parser (a -> b) -> Parser a -> Parser b` - `liftA2 :: (a -> b -> c) -> Parser a -> Parser b -> Parser c` - `(*>) :: Parser a -> Parser b -> Parser b` - `(<*) :: Parser a -> Parser b -> Parser a` ### Functor Parser - `fmap :: (a -> b) -> Parser a -> Parser b` - `(<$) :: a -> Parser b -> Parser a` ### Monad Parser - `(>>=) :: Parser a -> (a -> Parser b) -> Parser b` - `(>>) :: Parser a -> Parser b -> Parser b` - `return :: a -> Parser a` ### MonadPlus Parser - `mzero :: Parser a` - `mplus :: Parser a -> Parser a -> Parser a` ### Monoid (Parser a) - `mempty :: Parser a` - `mappend :: Parser a -> Parser a -> Parser a` - `mconcat :: [Parser a] -> Parser a` ### Semigroup (Parser a) - `(<>) :: Parser a -> Parser a -> Parser a` - `sconcat :: NonEmpty (Parser a) -> Parser a` - `stimes :: Integral b => b -> Parser a -> Parser a` ``` -------------------------------- ### Main Function for File I/O Source: https://hackage.haskell.org/package/cassava/docs/Data-Csv.html The main function orchestrates the CSV file operations by first writing data to 'persons.csv' and then reading it back. ```haskell {-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} -- from base import GHC.Generics import System.IO import System.Exit (exitFailure) -- from bytestring import Data.ByteString (ByteString, hGetSome, empty) import qualified Data.ByteString.Lazy as BL -- from cassava import Data.Csv.Incremental import Data.Csv (FromRecord, ToRecord) data Person = Person { name :: !ByteString , age :: !Int } deriving (Show, Eq, Generic) instance FromRecord Person instance ToRecord Person persons :: [Person] persons = [Person "John Doe" 19, Person "Smith" 20] writeToFile :: IO () writeToFile = do BL.writeFile "persons.csv" $ encode $ foldMap encodeRecord persons feed :: (ByteString -> Parser Person) -> Handle -> IO (Parser Person) feed k csvFile = do hIsEOF csvFile >>= \case True -> return $ k empty False -> k <$> hGetSome csvFile 4096 readFromFile :: IO () readFromFile = do withFile "persons.csv" ReadMode $ \ csvFile -> do let loop !_ (Fail _ errMsg) = do putStrLn errMsg; exitFailure loop acc (Many rs k) = loop (acc <> rs) =<< feed k csvFile loop acc (Done rs) = print (acc <> rs) loop [] (decode NoHeader) main :: IO () main = do writeToFile readFromFile ```