Is possible to create a haskell expression, using the methods in optparse-applicative, that parses program options like this?
program [-a [-b]] ...
-a and -b are optionals flags (implemented using switch), with the constraint that the -b option only is valid if -a is typed before.
Thanks
                        
This is possible, with slight tweaks, two different ways:
-bif you've got-a, but you can't insist then that the-acomes first, since optparse-applicative's<*>combinator doesn't specify an order.-boption follows theaoption, but you do this by implementingaas a command, so you lose the-in front of it.Applicative is definitely strong enough for this, since there's no need to inspect the values returned by the parsers to determine whether
-bis allowed, so>>=is not necessary; If-asucceeds with any output,-bis allowed.Examples
I'll use a data type to represent which arguments are present, but in reality these would be more meaningful.
So the options to our program maybe contain an A, which might have a B, and always have a string.
Way 1: standard combinators -
-bcan only come with-a(any order)I'll use
flag' () (short 'a')which just insists that-ais there, but then use*>instead of<*>to ignore the return value()and just return whatever theboptionparser returns, giving options-a [-b]. I'll then tag that withA :: Maybe B -> Aand finally I'll make the whole thingoptional, so you have options[-a [-b]]Notice that since
<*>allows any order, we can put-aafter-b(which isn't quite what you asked for, but works OK and makes sense for some applications).Way 2: command subparser -
-bcan only followaYou can use
commandto make asubparserwhich is only valid when the command string is present. You can use it to handle arguments like cabal does, so thatcabal installandcabal updatehave completely different options. Sincecommandtakes aParserInfoargument, any parser you can give toexecParsercan be used, so you can actually nest commands arbitrarily deeply. Sadly, commands can't start with-, so it'll beprogram [a [-b]] ...instead ofprogram [-a [-b]] ....Which runs like this:
So you have to precede
-bwitha.