1

I wrote a small parser with 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"

where sc and symbol and semiParser are from the tutorials. Now I would like to work with my result but I get a type error:

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! " }

So, my question is: how do I match against String -> Either (ParseError (Token String) Dec) String and get the error message or the result, if parsing failed?

I guess that the general form of this question is: How does pattern matching work? And I am confused in general how I can bind the result of a monad (such as Either in another monad, such as IO (I guess I have to pattern match and then lift the value into the context of the monad).

duplode
  • 33,731
  • 7
  • 79
  • 150

1 Answers1

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

You forgot that argument. Try

case parse semiParser "input name here" input of
chi
  • 111,837
  • 3
  • 133
  • 218