-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add example of incremental, name based parsing
There is already an example for indexed-based decoding, but not for name-based. This also adds a salaries.csv file, which is used by the new code, but incidentally closes #208
- Loading branch information
1 parent
c821c83
commit 25a109c
Showing
3 changed files
with
61 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
{-# LANGUAGE BangPatterns, ScopedTypeVariables, OverloadedStrings #-} | ||
|
||
import Control.Monad | ||
import qualified Data.ByteString as B | ||
import Data.Csv (FromNamedRecord(..), (.:)) | ||
import Data.Csv.Incremental | ||
import System.Exit | ||
import System.IO | ||
import Data.Either (rights) | ||
|
||
data SalaryInfo = SalaryInfo | ||
{ name :: String | ||
, salary :: Int | ||
} | ||
|
||
instance FromNamedRecord SalaryInfo where | ||
parseNamedRecord m = SalaryInfo <$> | ||
m .: "name" <*> | ||
m .: "salary" | ||
|
||
main :: IO () | ||
main = withFile "salaries.csv" ReadMode $ \ csvFile -> do | ||
|
||
let headerLoop (FailH _ errMsg) = putStrLn errMsg >> exitFailure | ||
headerLoop (PartialH fn) = headerLoop =<< feedHeader fn | ||
headerLoop (DoneH header parser) = loop 0 parser | ||
|
||
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) | ||
|
||
feedHeader k = do | ||
isEof <- hIsEOF csvFile | ||
if isEof | ||
then return $ k B.empty | ||
else k `fmap` B.hGetSome csvFile 4096 | ||
|
||
feed k = do | ||
isEof <- hIsEOF csvFile | ||
if isEof | ||
then return $ k B.empty | ||
else k `fmap` B.hGetSome csvFile 4096 | ||
headerLoop (decodeByName :: HeaderParser (Parser SalaryInfo)) | ||
where | ||
sumSalaries :: [Either String SalaryInfo] -> Int | ||
sumSalaries rs = | ||
let good = rights rs | ||
in sum $ map (\sinfo -> salary sinfo) good |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
name,salary | ||
Paul,100 | ||
Sam,200 |