ITADN

Accumulating error messages for failed fields when decoding named records

#231Opencgeorgii 创建于 2024-04-25
C
cgeorgiicommented
I currently have code that accumulates errors across rows, but reports only one error (for instance a missing field) per row. Is it somehow possible to list all missing fields when decoding a named record? Below the current code for reference, as well as how it behaves: ```haskell parseFromFile :: forall a. (FromNamedRecord a) => FilePath -> Char -> IO [Either String a] parseFromFile filepath delimiter = withFile filepath ReadMode $ \csvFile -> do let options = defaultDecodeOptions {decDelimiter = fromIntegral (ord delimiter)} loopHeader :: HeaderParser (Parser a) -> IO [Either String a] loopHeader (FailH _ errMsg) = pure [Left errMsg] loopHeader (PartialH contP) = feed contP >>= loopHeader loopHeader (DoneH _header parser) = loop [] parser loop :: [Either String a] -> Parser a -> IO [Either String a] loop !acc (Fail _ errMsg) = pure $ acc ++ [Left errMsg] loop !acc (Many result contP) = feed contP >>= loop (acc ++ result) loop !acc (Done result) = pure (acc ++ result) feed :: (ByteString -> f p) -> IO (f p) feed cont = do isEof <- hIsEOF csvFile if isEof then pure $ cont empty else cont <$> hGetSome csvFile 4096 loopHeader (Csv.Inc.decodeByNameWith options) ``` Running it against the following sample csv, yields the message as below: ``` # persons.csv name,age,yearsOfExperience John Doe,, Smith,20,4 # result [Left "in named field \"age\": expected Int, got \"\" (not enough input)",Right (Person {name = "Smith", age = 20, yearsOfExperience = 4})] ``` Ideally, the message would include the missing `age` _and_ the missing `yearsOfExperience` fields. Is it possible to achieve it?
2 条评论