I have
type Month = Int
parseMonths :: OP.Parser (Month, Month)
parseMonths =
liftA2 (,)
(OP.option
(OP.eitherReader $
parseNumber "month" (\n -> 1<=n && n<=12) "month")
(OP.metavar "MONTH" <>
OP.long "from-month" <>
OP.value 1))
(OP.option
(OP.eitherReader $
parseNumber "month" (\n -> 1<=n && n<=12) "month")
(OP.metavar "MONTH" <>
OP.long "to-month" <>
OP.value 12))
I want to add a check, that the first month is not after the second month. Obviously I cannot do that in OP.ReadM
. Can I perform the check in OP.Parser
? Or do I have to perform the check after parsing with parserFailure
like here:
Optparse-applicative: consecutive parsing (ReadM)
?
No.
Parser
is only anApplicative
and not aMonad
(hence the package name,optparse-applicative
). This is a typical feature of parser functors - because theApplicative
instance collects as many errors as possible, there is no possible lawfulMonad
instance.Without being a
Monad
, it's impossible to writeParser
s that depend on the result of otherParser
s - since that's the defining feature of monads.However,
optparse-applicative
does offer an escape hatch, if you really need one: useParserM
.ParserM
is basically an alternative toParser
which is aMonad
- at the cost of dropping error messages some of the time. You can write a monadic parser usingParserM
, and then userunParserM
to turn it back into a regularParser
.