README.md
1# `cassava`: A CSV parsing and encoding library [![Hackage](https://img.shields.io/hackage/v/cassava.svg)](https://hackage.haskell.org/package/cassava) [![Build Status](https://travis-ci.org/hvr/cassava.svg)](https://travis-ci.org/hvr/cassava)
2
3**Please refer to the [package description](https://hackage.haskell.org/package/cassava#description) for an overview of `cassava`.**
4
5## Usage example
6
7Here's the two second crash course in using the library. Given a CSV file with this content:
8
9```csv
10John Doe,50000
11Jane Doe,60000
12```
13
14here's how you'd process it record-by-record:
15
16```haskell
17{-# LANGUAGE ScopedTypeVariables #-}
18
19import qualified Data.ByteString.Lazy as BL
20import Data.Csv
21import qualified Data.Vector as V
22
23main :: IO ()
24main = do
25 csvData <- BL.readFile "salaries.csv"
26 case decode NoHeader csvData of
27 Left err -> putStrLn err
28 Right v -> V.forM_ v $ \ (name, salary :: Int) ->
29 putStrLn $ name ++ " earns " ++ show salary ++ " dollars"
30```
31
32If you want to parse a file that includes a header, like this one
33
34```csv
35name,salary
36John Doe,50000
37Jane Doe,60000
38```
39
40use [`decodeByName`](https://hackage.haskell.org/package/cassava/docs/Data-Csv.html#v:decodeByName):
41
42```haskell
43{-# LANGUAGE OverloadedStrings #-}
44
45import Control.Applicative
46import qualified Data.ByteString.Lazy as BL
47import Data.Csv
48import qualified Data.Vector as V
49
50data Person = Person
51 { name :: !String
52 , salary :: !Int
53 }
54
55instance FromNamedRecord Person where
56 parseNamedRecord r = Person <$> r .: "name" <*> r .: "salary"
57
58main :: IO ()
59main = do
60 csvData <- BL.readFile "salaries.csv"
61 case decodeByName csvData of
62 Left err -> putStrLn err
63 Right (_, v) -> V.forM_ v $ \ p ->
64 putStrLn $ name p ++ " earns " ++ show (salary p) ++ " dollars"
65```
66
67You can find more code examples in the [`examples/` folder](https://github.com/hvr/cassava/tree/master/examples) as well as smaller usage examples in the [`Data.Csv` module documentation](https://hackage.haskell.org/package/cassava/docs/Data-Csv.html).
68
69## Project Goals for `cassava`
70
71There's no end to what people consider CSV data. Most programs don't
72follow [RFC4180](https://tools.ietf.org/html/rfc4180) so one has to
73make a judgment call which contributions to accept. Consequently, not
74everything gets accepted, because then we'd end up with a (slow)
75general purpose parsing library. There are plenty of those. The goal
76is to roughly accept what the Python
77[`csv`](https://docs.python.org/3/library/csv.html) module accepts.
78
79The Python `csv` module (which is implemented in C) is also considered
80the base-line for performance. Adding options (e.g. the above
81mentioned parsing "flexibility") will have to be a trade off against
82performance. There's been complaints about performance in the past,
83therefore, if in doubt performance wins over features.
84
85Last but not least, it's important to keep the dependency footprint
86light, as each additional dependency incurs costs and risks in terms
87of additional maintenance overhead and loss of flexibility. So adding
88a new package dependency should only be done if that dependency is
89known to be a reliable package and there's a clear benefit which
90outweights the cost.
91
92## Further reading
93
94The primary API documentation for `cassava` is its Haddock documentation which can be found at http://hackage.haskell.org/package/cassava/docs/Data-Csv.html
95
96Below are listed additional recommended third-party blogposts and tutorials
97
98 - [CSV encoding and decoding in Haskell with Cassava](https://www.stackbuilders.com/tutorials/haskell/csv-encoding-decoding/)
99