如何匹配 megaparsec 结果?

How to match megaparsec result?

我用 megaparsec 写了一个小解析器:

module App (main) where

import Control.Monad (void)
import Text.Megaparsec
import Text.Megaparsec.String
import qualified Text.Megaparsec.Lexer as L

sc :: Parser ()
sc = L.space (void spaceChar) lineCmnt blockCmnt
  where lineCmnt  = L.skipLineComment "//"
        blockCmnt = L.skipBlockComment "/*" "*/"

symbol :: String -> Parser String
symbol = L.symbol sc

semiParser :: Parser String
semiParser = symbol ";"

main :: IO()
main = do
  input <- getLine
  case parse semiParser input of
    Left val -> putStrLn $ "Failed! "
    Right val -> putStrLn $ "Passed! "
  print "Done"

其中 sc 和符号以及 semiParser 来自教程。现在我想处理我的结果,但出现类型错误:

App.hs:23:5: error:
    • Couldn't match expected type ‘String
                                    -> Either (ParseError (Token String) Dec) String’
                  with actual type ‘Either t0 t1’
    • In the pattern: Left val
      In a case alternative: Left val -> putStrLn $ "Failed! "
      In a stmt of a 'do' block:
        case parse semiParser input of {
          Left val -> putStrLn $ "Failed! "
          Right val -> putStrLn $ "Passed! " }

App.hs:24:5: error:
    • Couldn't match expected type ‘String
                                    -> Either (ParseError (Token String) Dec) String’
                  with actual type ‘Either t2 t3’
    • In the pattern: Right val
      In a case alternative: Right val -> putStrLn $ "Passed! "
      In a stmt of a 'do' block:
        case parse semiParser input of {
          Left val -> putStrLn $ "Failed! "
          Right val -> putStrLn $ "Passed! " }

所以,我的问题是:如果解析失败,我如何匹配 String -> Either (ParseError (Token String) Dec) String 并获取错误消息或结果?

我想这个问题的一般形式是:模式匹配是如何工作的?而且我通常很困惑如何将一个 monad 的结果(例如 Either 绑定到另一个 monad,例如 IO (我想我必须进行模式匹配,然后将值提升到上下文中单子的)。

parse :: Stream s Identity t => Parsec s () a -> SourceName -> s -> Either ParseError a 
                                              -- ^^^^^^^^^^ --

你忘了那个论点。尝试

case parse semiParser "input name here" input of