是否可以使用optparse-applicative中的方法创建一个 haskell 表达式来解析这样的程序选项?
program [-a [-b]] ...
-a和-b是可选标志(使用 实现switch
),约束是-b选项只有在-a之前键入时才有效。
谢谢
是否可以使用optparse-applicative中的方法创建一个 haskell 表达式来解析这样的程序选项?
program [-a [-b]] ...
-a和-b是可选标志(使用 实现switch
),约束是-b选项只有在-a之前键入时才有效。
谢谢
这是可能的,只需稍作调整,有两种不同的方式:
-b
您可以制作一个仅在您拥有时才允许的解析器-a
,但您不能坚持认为-a
首先出现,因为 optparse-applicative 的<*>
组合器没有指定顺序。-b
选项遵循该a
选项,但是您通过a
作为命令实现来做到这一点,因此您失去了-
它前面的。Applicative 绝对足够强大,因为不需要检查解析器返回的值来确定是否-b
允许,所以>>=
没有必要;如果任何输出-a
成功,则允许。-b
我将使用数据类型来表示存在哪些参数,但实际上这些会更有意义。
import Options.Applicative
data A = A (Maybe B) deriving Show
data B = B deriving Show
所以我们程序的选项可能包含一个 A,它可能有一个 B,并且总是有一个字符串。
boption :: Parser (Maybe B)
boption = flag Nothing (Just B) (short 'b')
-b
只能附带-a
(任何顺序)我将使用flag' () (short 'a')
which 只是坚持-a
存在,但随后使用*>
而不是<*>
忽略返回值()
,只返回boption
解析器返回的任何内容,并给出 options -a [-b]
。然后我会标记它,A :: Maybe B -> A
最后我会做整个事情optional
,所以你有选择[-a [-b]]
aoption :: Parser (Maybe A)
aoption = optional $ A <$> (flag' () (short 'a' ) *> boption)
main = execParser (info (helper <*> aoption)
(fullDesc <> progDesc "-b is only valid with -a"))
>>= print
请注意,由于<*>
允许任何订单,我们可以放在-a
后面-b
(这不是您所要求的,但可以正常工作并且对某些应用程序有意义)。
ghci> :main -a
Just (A Nothing)
ghci> :main -a -b
Just (A (Just B))
ghci> :main -b -a
Just (A (Just B))
ghci> :main -b
Usage: <interactive> [-a] [-b]
-b is only valid with -a
*** Exception: ExitFailure 1
-b
只能跟随a
您可以command
用来制作subparser
仅在命令字符串存在时才有效的 a。cabal install
您可以使用它来处理像 cabal 那样的参数,因此cabal update
具有完全不同的选项。由于command
需要一个ParserInfo
参数,因此可以使用您可以提供的任何解析器execParser
,因此您实际上可以任意深度嵌套命令。可悲的是,命令不能以 . 开头-
,所以它会program [a [-b]] ...
代替program [-a [-b]] ...
.
acommand :: Parser A
acommand = subparser $ command "a" (info (A <$> (helper <*> boption))
(progDesc "you can '-b' if you like with 'a'"))
main = execParser (info (helper <*> optional acommand) fullDesc) >>= print
像这样运行:
ghci> :main
Nothing
ghci> :main a
Just (A Nothing)
ghci> :main a -b
Just (A (Just B))
ghci> :main -b a
Usage: <interactive> [COMMAND]
*** Exception: ExitFailure 1
所以你必须在前面-b
加上a
.
恐怕你不能。这恰恰是Applicative
一个人无法处理的场景,而Monad
可以:根据早期的结果改变后面的动作的结构。在应用计算中,总是需要事先知道“形状”;这有一些优点(比如加速 so 数组组合,或者为命令行选项提供一个很好的可读帮助屏幕),但在这里它限制您解析“平面”选项。
optparse-applicative 的接口也有Alternative
,它确实允许依赖解析,尽管方式不同,如 AndrewC 所示。