Вы можете добавить guard
как предложил Томас М. Dubuisson:
date :: Parser (String, String, String)
date = do
year <- replicateM 4 digit
month <- replicateM 2 digit
day <- replicateM 2 digit
guard $ read month > 0 && read month <= 12 && read day > 0 && read day <= 31
return (year, month, day)
Однако, это приводит к плохим сообщением об ошибке:
λ> parse date "" "20161356"
Left (line 1, column 9):unknown parse error
Мы можем исправить это путем объединения guard
с <?>
для обеспечения лучшего сообщения об ошибке:
date :: Parser (String, String, String)
date = do
year <- replicateM 4 digit
month <- replicateM 2 digit
guard (read month > 0 && read month <= 12) <?> "valid month (1–12)"
day <- replicateM 2 digit
guard (read day > 0 && read day <= 31) <?> "valid day (1–31)"
return (year, month, day)
При таком подходе вы получите более полезное сообщение об ошибке:
λ> parse date "" "20161356"
Left (line 1, column 7):
expecting valid month (1–12)
Как примечание стороны, я думаю, что это является ценными для подтверждения (или, по крайней мере, проверка исправности) дата в парсер-он гарантирует, что проверка даты выполняется вместе с остальным вашим парсером и кодом обработки ошибок. Вы не можете забыть проверить дату позже в своем коде, и ошибка локализована правильно, что очень полезно, если вы разбираете документы с большим количеством дат.
'guard $ month> = 0 && month <= 12'? –
'> = 1' возможно? : D – ThreeFx
Сторона примечания 20160229 действительна, в то время как 20000229 не является, не нужно угадывать, что слишком – epsilonhalbe