10

I was expecting to find a function

integer :: Stream s m Char => ParsecT s u m Integer

or maybe even

natural :: Stream s m Char => ParsecT s u m Integer

in the standard libraries, but I did not find one.

What is the standard way of parsing plain natural numbers directly to an Integer?

Joachim Breitner
  • 25,395
  • 6
  • 78
  • 139

3 Answers3

14

Here is what I often do is to use the expression

read <$> many1 digit

which can have type Stream s m Char => ParsecT s u m Integer (or simply Parser Integer).

I don’t like the use of the the partial function read, but when the parser succeeds I know that the read will succeed, and it is somewhat readable.

Joachim Breitner
  • 25,395
  • 6
  • 78
  • 139
2

Looking at the source of Text.Parsec.Token, it seems Parsec doesn't have a dedicated function for it. They do give a default definition for the decimal field of GenLanguageDef. decimal is defined similar to:

decimal = do
    digits <- many1 baseDigit
    let n = foldl (\x d -> base*x + toInteger (digitToInt d)) 0 digits
    seq n (return n)
  where
    base = 10
    baseDigit = digit

Here, digit is taken from Text.Parsec.Char and digitToInt from Data.Char.

There's also a default definition for natural, which, by default, also parses octal and hexadecimal numbers, and skips trailing whitespace.

  • Also, [this answer](http://stackoverflow.com/a/10726784/824425) is really similar, quite a bit shorter thanks to its applicative style, and uses `foldl'` instead of `foldl` plus a `seq` at the wrong place :) –  Jun 11 '14 at 19:52
1

There is a package parsec3-numbers [hackage] that provides functions to parse numbers in some formats.

Probably the most interesting ones are int :: (Integral i, Stream s m Char) => ParsecT s u m i and nat :: (Integral i, Stream s m Char) => ParsecT s u m i which parse integral numbers and natural numbers respectively. These do not only parse the numbers as decimal format, but also as octal and hexadecimal. The package also contains some parsers that restrict parsing with a specific radix, so only decimal numbers for example.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555