module TSV ( parseTSV, formatTSV ) where import Data.List -- Simple implementation of tab-separated values with a trailing newline and no -- quoting support. splitList :: Eq a => a -> Bool -> [a] -> [[a]] splitList delim terminated = let sl [] | terminated = [] sl l = case break (== delim) l of (hh, []) -> [hh] (hh, {-delim-} _ : t) -> hh : sl t in sl -- We use the Eq only to check the validity... joinList :: Eq a => a -> Bool -> [[a]] -> [a] joinList delim terminated l = if any (any (== delim)) l then error "joinList: item contains delimiter" else if terminated then concatMap (++ [delim]) l else intercalate [delim] l type TSV = [[String]] formatTSV :: TSV -> String formatTSV = joinList '\n' True . map (joinList '\t' False) parseTSV :: String -> TSV parseTSV = map (splitList '\t' False) . splitList '\n' True