parsinghaskellfunctional-programmingparser-combinators

readP in Haskell has output that doesn't match the intended input when using the string


I am trying to write a simple parser in Haskell using readP and following some pre-made code examples I have found.

I use the following:

import Text.ParserCombinators.ReadP
import Control.Applicative ((<|>))

t :: ReadP Int
t = (do string "0"
        return 0)
    <|>
    (do string "1"
        return 1)

parseString = readP_to_S (t >> eof)

However I get the following output:

ghci> parseString "1"
[((),"")]
ghci> parseString "0"
[((),"")]
ghci> parseString ""
[]

Whereas I would expect the following output

ghci> parseString "1"
[("1","")]
ghci> parseString "0"
[("0","")]
ghci> parseString ""
[]

How come that is? And is there a way to make it print these outputs instead?


Solution

  • The new code is better, but there is still an issue here

    parseString input = runParser (e >> eof) input
                                --^^^^^^^^^^--
    

    Adding >> eof discards the result of e. To retain it, we can either use

    parseString input = runParser (e <* eof) input
    

    Or, with a more basic approach:

    whole :: Parser Int
    whole = do
       val <- e       -- save the value produced by e
       eof            -- ensure the end of the parsed string
       return val     -- return the saved value
    
    parseString input = runParser whole input
    

    In either case, we get:

    > parseString "1"
    [(1,"")]
    

    Note that the first component of the pair in the list is 1, an Int. Indeed, it has the same type mentioned in the signature whole :: Parser Int.