我已经使用Parsec定义了一个解析器,它对某些Parsec Text () a
具有类型a
。我还具有“处理此块的功能”功能,该功能将我解析的内容写入文件中,类型为a -> IO ()
。解析的文件格式意味着我们相当频繁地回到“顶级”。
是否有办法将我原来的解析器“提升”到IO monad中?我正在想象带有以下类型签名的东西:
liftParser :: Parsec Text () a -> (a -> IO ()) -> ParsecT Text () IO ()
第一个参数是纯解析器,第二个参数是“用我解析的东西做某事”功能。
很显然,我也可以通过在IO中重新定义原始解析器来组合所需的东西,但这意味着我的单元测试看起来很可怕,而且感觉像是错误的方法。
此外,我不能像调用runParserT
那样疯狂,因为那样会丢弃源位置信息-如果输入的第1000行出现错误,我希望错误消息这样说。
那么有办法做到这一点吗?另外,这是明智的做法吗?我想至少要设法避免累积输出数据。而且,假设我管理类似的事情,我应该期望Parsec
放弃已处理的输入数据吗?
答案 0 :(得分:0)
因此可以将此问题标记为已回答:上面luqui的评论解释了如何做到这一点。
诀窍是用ParsecT Text () m
类型多态地定义所有解析器(所有定义最终看起来像thing :: Monad m => Parsec Text () m MyType
)。然后,您可以在测试台中用m
实例化身份monad,并等于使用它们的IO
。