如何在避免使用unsafePerformIO的同时嵌套Parser(IO a)?

vpo*_*yev 1 io haskell parsec icu

在玩基于text-icu的解析时BreakIterator,我一直坚持实现这样的功能

conditionalParser :: (a -> Bool) -> Parser a -> Parser a -> Parser a -> Parser a
conditionalParser f a b c = do
        a' <- a
        if f a'
                then b
                else c
Run Code Online (Sandbox Code Playgroud)

但有一种类型

conditionalParserIO :: (a -> Bool) -> Parser (IO a) -> Parser (IO a) -> Parser (IO a) -> Parser (IO a)
Run Code Online (Sandbox Code Playgroud)

没有做可能unsafePerformIO吗?

到目前为止,我只能得到一些do具有最终返回类型的嵌套s Parser (IO (Parser (IO a))),但不知道如何折叠它们.

Yel*_*ika 6

我想你想要的是用ParsecT而不是Parser.

conditionalParserM :: Monad m => (a -> Bool) -> ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
conditionalParserM f a b c = do
    a' <- a
    if f a' then b else c
Run Code Online (Sandbox Code Playgroud)

此功能适用于所有类型的Monads,而不仅仅是IO.

我想可以从a转换ParsecT s u IO aParser (IO a)使用runParsecT,具体取决于你使用的是哪个Parser(这个这个?).但是,我建议您只需重新构建代码即可ParsecT.


澄清

conditionalParserM不能用作替代品conditionalParserIO.我建议您需要更改程序的工作方式,因为尝试做您正在做的事情(没有unsafePerformIO,您几乎不应该使用)是不可能的.

您希望根据IO操作的结果组合解析器,这意味着解析器本身在运行时会执行副作用.为了将其封装在类型中,您需要使用monad转换器.

因此,要使用conditionalParserM,您需要重新构建代码以使用ParsecT而不是Parser.