purescript-csv-stream/src/Data.CSV.Record.purs

51 lines
1.9 KiB
Haskell
Raw Normal View History

2024-04-30 18:39:51 +00:00
module Data.CSV.Record where
import Prelude
import Control.Monad.Error.Class (liftMaybe)
import Control.Monad.Except (Except)
import Data.Array as Array
import Data.CSV (class ReadCSV, class WriteCSV, readCSV, writeCSV)
import Data.List.NonEmpty (NonEmptyList)
2024-05-01 14:50:55 +00:00
import Data.Map (Map)
import Data.Map as Map
2024-04-30 18:39:51 +00:00
import Data.Maybe (fromMaybe)
2024-05-01 14:50:55 +00:00
import Data.Symbol (class IsSymbol, reflectSymbol)
2024-04-30 18:39:51 +00:00
import Foreign (ForeignError(..))
import Prim.Row (class Cons, class Lacks)
import Prim.RowList (class RowToList, Cons, Nil, RowList)
import Record as Record
import Type.Prelude (Proxy(..))
class WriteCSVRecord :: Row Type -> RowList Type -> Constraint
class RowToList r rl <= WriteCSVRecord r rl | rl -> r where
writeCSVRecord :: { | r } -> Array String
instance (RowToList r (Cons k v tailrl), IsSymbol k, WriteCSV v, Lacks k tail, Cons k v tail r, WriteCSVRecord tail tailrl) => WriteCSVRecord r (Cons k v tailrl) where
writeCSVRecord r =
let
val = writeCSV $ Record.get (Proxy @k) r
tail = writeCSVRecord @tail @tailrl $ Record.delete (Proxy @k) r
in
[ val ] <> tail
2024-04-30 18:39:51 +00:00
instance WriteCSVRecord () Nil where
writeCSVRecord _ = []
class ReadCSVRecord :: Row Type -> RowList Type -> Constraint
class RowToList r rl <= ReadCSVRecord r rl | rl -> r where
2024-05-01 14:50:55 +00:00
readCSVRecord :: Map String Int -> Array String -> Except (NonEmptyList ForeignError) { | r }
2024-04-30 18:39:51 +00:00
instance (RowToList r (Cons k v tailrl), IsSymbol k, ReadCSV v, Lacks k tail, Cons k v tail r, ReadCSVRecord tail tailrl) => ReadCSVRecord r (Cons k v tailrl) where
2024-05-01 14:50:55 +00:00
readCSVRecord cols vals = do
let
k = reflectSymbol (Proxy @k)
pos <- liftMaybe (pure $ ForeignError $ "row too long; did not expect value " <> k) $ Map.lookup k cols
2024-05-01 15:12:51 +00:00
let valraw = fromMaybe "" $ Array.index vals pos
2024-04-30 18:39:51 +00:00
val <- readCSV @v valraw
2024-05-01 15:25:08 +00:00
tail <- readCSVRecord @tail @tailrl cols vals
2024-04-30 18:39:51 +00:00
pure $ Record.insert (Proxy @k) val tail
instance ReadCSVRecord () Nil where
2024-05-01 14:50:55 +00:00
readCSVRecord _ _ = pure {}