50 lines
1.3 KiB
Haskell
50 lines
1.3 KiB
Haskell
{-# LANGUAGE FlexibleContexts,
|
|
TypeFamilies,
|
|
NoMonomorphismRestriction #-}
|
|
import Data.List (intercalate)
|
|
import Data.List.Split (splitOn)
|
|
import Lens.Micro
|
|
|
|
(<$$>) :: (Functor f1, Functor f2) =>
|
|
(a -> b) -> f1 (f2 a) -> f1 (f2 b)
|
|
(<$$>) = fmap . fmap
|
|
|
|
------------------------------------------------------------
|
|
-- reading and writing
|
|
|
|
newtype CSV = CSV { values :: [[String]] }
|
|
|
|
readCSV :: String -> CSV
|
|
readCSV = CSV . (splitOn "," <$$> lines)
|
|
|
|
instance Show CSV where
|
|
show = unlines . map (intercalate ",") . values
|
|
|
|
------------------------------------------------------------
|
|
-- construction and combination
|
|
|
|
mkColumn, mkRow :: [String] -> CSV
|
|
(<||>), (<==>) :: CSV -> CSV -> CSV
|
|
|
|
mkColumn lst = CSV $ sequence [lst]
|
|
mkRow lst = CSV [lst]
|
|
|
|
CSV t1 <||> CSV t2 = CSV $ zipWith (++) t1 t2
|
|
CSV t1 <==> CSV t2 = CSV $ t1 ++ t2
|
|
|
|
------------------------------------------------------------
|
|
-- access and modification via lenses
|
|
|
|
table = lens values (\csv t -> csv {values = t})
|
|
row i = table . ix i . traverse
|
|
col i = table . traverse . ix i
|
|
item i j = table . ix i . ix j
|
|
|
|
------------------------------------------------------------
|
|
|
|
sample = readCSV "C1, C2, C3, C4, C5\n\
|
|
\1, 5, 9, 13, 17\n\
|
|
\2, 6, 10, 14, 18\n\
|
|
\3, 7, 11, 15, 19\n\
|
|
\4, 8, 12, 16, 20"
|