Search code examples
haskellparsec

Adding readHex to a Parsec parser


I'm going through Write Yourself a Scheme and am struck at the exercise 4 on this page.

How do I go about this? I've got this far, but have no idea whatsoever where the readHex is supposed to go, must I liftM it ? Do you case match the parser ?

parseNumber = liftM (Number . read) $ choice [many1 digit, char '#' >> oneOf "hd" >>= a]
    where a f = case f of
        'h' -> many1 digit

Also, I don't suppose you can apply <|> on Parser LispVal functions, right?


Solution

  • I've got this far, but have no idea whatsoever where the readHex is supposed to go, must I liftM it ?

    Yes, since readHex is most likely a pure function and liftM lifts it into the monadic context of Parser.

    Since I don't quite understand what your local function a is good for, I'm leaving it for now and simply use the functions parseDecimal and parseHex. In that case, you could write parseNumber like so:

    parseNumber :: Parser LispVal
    parseNumber = liftM Number $ parseDecimal <|> parseHex
        where parseDecimal :: Parser Integer
              parseDecimal = liftM read $ many1 digit
              parseHex :: Parser Integer
              parseHex     = liftM readHex $ char '#' >> ... -- parse hex value
    

    Of course you can omit the type signatures, I just added them for clarity.

    Also, I don't suppose you can apply <|> on Parser LispVal functions, right?

    <|> works for every Parser a.

    I recommend reading some material on parser combinators, i.e. the Parsec User Guide.