Search code examples
haskellconduit

Can I set the column order for conduit-CSV using NamedRecords?


My code is below. It seems like the data gets output in a random order, which makes sense since NamedRecord is just a Map. Is there a way I can enforce a specific order?

I think one option is to create a conduit of type Conduit (Named a) m (Row Text), but it seems like this is a common enough use case that something standard should already exist.

processor :: Monad m => Conduit (Named FalconRow) m (Named HefRow)
processor = do
  value <- await 
  case value of
    Nothing -> return ()
    Just v -> do
      let transformed = (fixRow . getNamed) v
      CL.sourceList $ Prelude.map Named transformed

runTranslation :: IO ()
runTranslation = runResourceT $ 
  transformCSV defCSVSettings 
               (sourceFile "input.csv") 
               processor
               (sinkFile "output.csv")

Solution

  • I ended up just making my own function for this:

    sortColumns :: (Monad m, DefaultOrdered a, ToNamedRecord a) => Conduit (Named a) m (Row ByteString)
    sortColumns = CL.map doSort
    
    doSort :: (DefaultOrdered a, ToNamedRecord a) => Named a -> Row ByteString
    doSort value =
      let columnMap = toNamedRecord $ getNamed value
          headers = toList $ headerOrder $ getNamed value
          bsValue = map (\title -> findWithDefault "" title columnMap) headers
      in  bsValue