Haskell cassava (Data.Csv):忽略缺失的列/字段



我如何设置木薯忽略缺失的列/字段,并用默认值填充相应的数据类型?考虑这个例子:

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
import           Data.ByteString.Lazy.Char8
import           Data.Csv
import           Data.Vector
import           GHC.Generics
data Foo = Foo { 
a :: String
, b :: Int
} deriving (Eq, Show, Generic)

instance FromNamedRecord Foo
decodeAndPrint :: ByteString -> IO ()
decodeAndPrint csv = do
print $ (decodeByName csv :: Either String (Header, Vector Foo))
main :: IO ()
main = do
decodeAndPrint "a,b,ignorenhu,1,pu"  -- [1]
decodeAndPrint "ignore,b,anpu,1,hu"  -- [2]
decodeAndPrint "ignore,bnpu,1"     -- [3]

[1][2]工作完全正常,但[3]

时失败。
Left "parse error (Failed reading: conversion error: no field named "a") at """

我怎样才能使decodeAndPrint能够处理这个不完整的输入?

我当然可以操作输入字节串,但也许有一个更优雅的解决方案。


解决方案感谢Daniel Wagner的输入:

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
import           Control.Applicative
import           Data.ByteString.Lazy.Char8
import           Data.Csv
import           Data.Vector
import           GHC.Generics
data Foo = Foo { 
a :: Maybe String
, b :: Maybe Int
} deriving (Eq, Show, Generic)

instance FromNamedRecord Foo where
parseNamedRecord rec = pure Foo
<*> ((Just <$> Data.Csv.lookup rec "a") <|> pure Nothing)
<*> ((Just <$> Data.Csv.lookup rec "b") <|> pure Nothing)
decodeAndPrint :: ByteString -> IO ()
decodeAndPrint csv = do
print $ (decodeByName csv :: Either String (Header, Vector Foo))
main :: IO ()
main = do
decodeAndPrint "a,b,ignorenhu,1,pu"  -- [1]
decodeAndPrint "ignore,b,anpu,1,hu"  -- [2]
decodeAndPrint "ignore,bnpu,1"       -- [3]

(警告:完全未经测试!代码仅用于思想传递,不适合任何用途等)

FromNamedRecord所要求的Parser类型是Alternative,所以只需将(<|>)默认设置为。

instance FromNamedRecord Foo where
parseNamedRecord rec = pure Foo
<*> (lookup rec "a" <|> pure "missing")
<*> (lookup rec "b" <|> pure 0)

如果你以后想知道这个字段是否存在,让你的字段足够丰富以记录:

data RichFoo = RichFoo
{ a :: Maybe String
, b :: Maybe Int
}
instance FromNamedRecord Foo where
parseNamedRecord rec = pure RichFoo
<*> ((Just <$> lookup rec "a") <|> pure Nothing)
<*> ((Just <$> lookup rec "b") <|> pure Nothing)

最新更新