简体   繁体   中英

Parsec and liftIO, compilation error

I'm parsing a language and I want to have syntax to $include other files while parsing.

My code:

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

The error message from 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 '"';
           .... }

How can I make it work?

IMO the parsing stage is not the right place to import files. I suggest you parse the file as a whole and process the result after you are done.

If you want to process the $include directives while parsing, you'll need to run over IO . Parsec exposes a monad transformer for this purpose called ParsecT ; if you change the type of notaInclude to ParsecT String () IO [SourceItem] it should work.

However, in general I would side with @soupi's suggestion , and keep parsing pure and resolve $include s after parsing. But maybe you have some good reason to do it this way for your particular application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM