在IO monad中使用parsec解析器

时间:2019-03-22 18:19:27

标签: haskell monads parsec io-monad

我已经使用Parsec定义了一个解析器,它对某些Parsec Text () a具有类型a。我还具有“处理此块的功能”功能,该功能将我解析的内容写入文件中,类型为a -> IO ()。解析的文件格式意味着我们相当频繁地回到“顶级”。

是否有办法将我原来的解析器“提升”到IO monad中?我正在想象带有以下类型签名的东西:

liftParser :: Parsec Text () a -> (a -> IO ()) -> ParsecT Text () IO ()

第一个参数是纯解析器,第二个参数是“用我解析的东西做某事”功能。

很显然,我也可以通过在IO中重新定义原始解析器来组合所需的东西,但这意味着我的单元测试看起来很可怕,而且感觉像是错误的方法。

此外,我不能像调用runParserT那样疯狂,因为那样会丢弃源位置信息-如果输入的第1000行出现错误,我希望错误消息这样说。

那么有办法做到这一点吗?另外,这是明智的做法吗?我想至少要设法避免累积输出数据。而且,假设我管理类似的事情,我应该期望Parsec放弃已处理的输入数据吗?

1 个答案:

答案 0 :(得分:0)

因此可以将此问题标记为已回答:上面luqui的评论解释了如何做到这一点。

诀窍是用ParsecT Text () m类型多态地定义所有解析器(所有定义最终看起来像thing :: Monad m => Parsec Text () m MyType)。然后,您可以在测试台中用m实例化身份monad,并等于使用它们的IO