使用Cassava与Attoparsec解析自定义字段时如何实现FromField实例
实现方案
你只需要把写好的解析逻辑套入Cassava FromField 实例的字段处理流程即可,核心逻辑是:把Cassava传入的字段ByteString送入解析器执行,将解析结果适配为Cassava要求的Parser monad返回值即可。
前置依赖
默认你用的是Attoparsec编写的解析器(和Cassava的内置解析依赖一致),需要先导入相关模块:
import Data.Csv (FromField(..)) import Data.Attoparsec.ByteString (parseOnly, (<|>), double, string, endOfInput)
完整实现代码
首先建议给原有解析逻辑加上endOfInput,避免出现前缀匹配的问题(比如10Fxxx这种非法值也被解析成功):
data EValue = Farads Double | MicroFarads Double | PicoFarads Double deriving (Eq, Show) parseEValue = farads <|> micro <|> pico <* endOfInput where farads = Farads <$> double <* string "F" micro = MicroFarads <$> double <* string "µF" pico = PicoFarads <$> double <* string "pF"
然后填写FromField实例即可:
instance FromField EValue where parseField bs = case parseOnly parseEValue bs of -- 解析失败时抛出Cassava可识别的错误信息 Left parseErr -> fail $ "无法解析电容值: " ++ parseErr Right ev -> pure ev
注意事项
- 如果你用的是Parsec而非Attoparsec编写解析逻辑,只需要把
parseOnly替换为Parsec对应的运行解析函数即可,整体逻辑不变。 - 注意
µ符号的编码匹配:如果你的CSV文件不是UTF-8编码,需要把string "µF"对应的字节序列调整为和文件编码一致,避免单位匹配失败。
内容的提问来源于stack exchange,提问作者GTF
相关产品推荐
相关产品推荐

