【问题标题】:Parsec and liftIO, compilation errorParsec 和 liftIO,编译错误
【发布时间】:2016-03-24 01:11:05
【问题描述】:

我正在解析一种语言,我希望在解析时使用$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 '"';
           .... }

我怎样才能让它工作?

【问题讨论】:

  • 您不能在Parser 内执行IO,但如果您将解析器类型更改为ParsecT String () IO,它将起作用。

标签: haskell parsec io-monad


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    但是,总的来说,我会支持@soupi's suggestion,并保持解析纯并在解析后解析$includes。但也许您有充分的理由为您的特定应用程序这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-28
      • 2012-10-12
      • 2011-10-12
      • 2018-02-01
      • 2017-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多