cassava icon indicating copy to clipboard operation
cassava copied to clipboard

Write to multiple records (multiline `toRecord`?)

Open jkr opened this issue 8 years ago • 1 comments

I sometimes need to encode types that have multiple records in them, something like:

data Observation = Obvervation {
   foo :: Integer
 , bar :: Integer
 }

data DayInTheField = DayInTheField { 
   day :: String, 
 , place :: String
 , observations :: [Observation]
 }

and, ideally, I'd like to encode each observation to its own record line. So:

DayInTheField{ 
   day="Monday"
 , place="Baltimore"
 , observations=[Observation 1 2, Observation 3 4]
}

would encode to

day,place,foo,bar
Monday,Baltimore,1,2
Monday,Baltimore,3,4

Is that something that is possible with cassava? If not, is that a wishlist item that might be considered? I imagine it would either require a redefinition of Record or an intermediate type between Record and CSV (say, RecordChunk), so I can see that it might be intrusive.

jkr avatar Jan 05 '16 17:01 jkr

In case anyone else comes across this, I implemented an ad-hoc solution by creating a new typeclass, and related encode functions:

class ToManyRecords x where
  toRecords :: x -> [Record]

csvEncodeManyWith :: ToManyRecords a => EncodeOptions -> [a] -> ByteString
csvEncodeManyWith opts xs = encodeWith opts (concatMap toRecords xs)

csvEncodeMany :: ToManyRecords a => [a] -> ByteString
csvEncodeMany = csvEncodeManyWith defaultEncodeOptions

And writing instance for my types. Using the made-up type above, I'd have

instance ToRecord Observation where
  toRecord obs = record [ toField $ foo obs
                        , toField $ bar obs
                        ]

instance ToManyRecords DayInTheField where
  toRecords ditf = map (record' <>) (map toRecord $ observations ditf)
    where record' = record [ toField $ day ditf
                           , toField $ place ditf
                           ]

I can then run csvEncodeMany on some [DayInTheField] to get what I need.

I'm leaving this open, though, unless you think I should close it, because it does seem like a feature which, in a more thought-out way, might be useful to some users.

jkr avatar Jan 06 '16 21:01 jkr