[Haskell-beginners] Parsec and Validation

Vladimir Solmon vvvladistan at gmail.com
Sat Jul 31 15:57:07 EDT 2010


I'm attempting to use Parsec to write a parser for times and dates.
I'm aware of Data.Time.Format, but it doesn't offer the flexibility I
need for this project.

My current code (see below) uses Control.Monad.guard to validate the
numeric values for hours and minutes inside the parser. The problem
I'm running into is that checking for errors in the parsing code
causes Text.Parsec.Combinator.choice (in the time function below) to
fail and return an error if it cannot parse input using the first
option (tTimeHourMin), even if the input should match the second
option (t24hrClock).

I have several questions:

Why is choice failing in the time function below?

Is there a better way to do numeric validation while parsing?

Should I only use Parsec to validate that the input is syntactically
correct and do the numeric validation elsewhere?

What are some good examples of validating input using Parsec?


Here is a bit of the code I'm working with:

time :: Parser TimeOfDay
time = choice [ tTimeHourMin,
                          t24hrClock
                       ]

tTimeHourMin :: Parser TimeOfDay
tTimeHourMin = do
    hour <- range (0, 23)
    oneOf " :,."
    min <- range (0, 59)
    return (TimeOfDay hour min 0)

t24hrClock :: Parser TimeOfDay
t24hrClock = do
    (h, m) <- splitAt 2 <$> count 4 digit
    let hour = read h
    let min = read m
    guard (hour >= 0 && hour <= 23 && min >= 0 && min <= 59)
      <?> printf "24hr time represented as hhmm"
    return (TimeOfDay hour min 0)

range :: (Int,Int) -> Parser Int
range (lower, upper) = do
   t <- read <$> many1 digit
   guard (t >= lower && t <= upper)
     <?> printf "integer in range [%d,%d]" lower upper
   return t


Thanks for any suggestions,

vladimir


More information about the Beginners mailing list