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

130 views Asked by At

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?

1

There are 1 answers

0
chi On BEST ANSWER

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.