Skip to content

Instantly share code, notes, and snippets.

@eviltwin
Created November 8, 2013 11:00
Show Gist options
  • Save eviltwin/7369467 to your computer and use it in GitHub Desktop.
Save eviltwin/7369467 to your computer and use it in GitHub Desktop.
Haskell Simple CSV Parsing
--
-- CSV parsing code.
--
-- Doesn't handle escaping or quotes, but could be expanded to do so. Input data
-- must contain at least the header row, otherwise pattern matches will fail.
--
readCsv :: String -> IO Csv
-- ^Reads a CSV file of the given name and returns the parsed contents.
readCsv = (parseCsv `fmap`) . readFile
parseCsv :: String -> Csv
-- ^Parses a string as a CSV file with a header as the first row.
parseCsv = liftM2 Csv head tail . map parseCsvLine . lines
-- The above version of parseCsv SHOULD get optimised by the compiler so that
-- the separate calls to head and tail aren't done wastefully. The below version
-- is the original function before I made it point-free...
--parseCsv csv = let (h : rs) = map parseCsvLine $ lines csv in Csv h rs
parseCsvLine :: String -> [String]
-- ^Parses a single line of CSV data.
parseCsvLine = split (== ',')
split :: (Char -> Bool) -> String -> [String]
-- ^Helper function for splitting a string on a predicate.
split p = unfoldr (fmap f) . Just
where
f s = let (v, s') = break p s
in (v, if (null s') then Nothing
else Just (tail s'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment