
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