Parsec和liftIO,编译错误

时间:2016-03-24 01:11:05

标签: haskell parsec io-monad

我正在解析一种语言,我想在解析时为$include其他文件提供语法。

我的代码:

import Text.ParserCombinators.Parsec
import Text.Parsec.Prim (parserZero)
import Text.ParserCombinators.Parsec.Char
import Control.Monad.Trans
import Data.Functor.Identity

notaInclude :: Parser [SourcesItem]
notaInclude = do
    try $ string "$Include" >> blanks1
    char '"'
    fileName <- quotedStringParser
    char '"'
    i <- getInput
    included <- liftIO $ readFile fileName
    setInput included
    si <- sources
    setInput i
    return si

来自GHC的错误消息:

Lazi/Lazi'nh/Language/Sources/Parser.hs:65:17:
    No instance for (MonadIO Identity) arising from a use of `liftIO'
    Possible fix: add an instance declaration for (MonadIO Identity)
    In the expression: liftIO
    In a stmt of a 'do' block: included <- liftIO $ readFile fileName
    In the expression:
      do { try
             (do { string "$Include";
                   blanks1 });
           char '"';
           fileName <- quotedStringParser;
           char '"';
           .... }

我怎样才能让它发挥作用?

2 个答案:

答案 0 :(得分:1)

IMO解析阶段不是导入文件的正确位置。我建议您将文件整体解析,并在完成后处理结果。

答案 1 :(得分:0)

如果要在解析时处理$include指令,则需要运行IO。 Parsec为此目的公开了一个名为ParsecT的monad变换器;如果您将notaInclude的类型更改为ParsecT String () IO [SourceItem]则应该有效。

但是,一般来说,我会支持@soupi's suggestion,并在解析后继续解析纯粹并解析$include。但也许你有充分的理由以这种方式为你的特定应用做到这一点。