是否可以使用optparse-applicative中的方法创建一个haskell表达式来解析这样的程序选项?
program [-a [-b]] ...
-a 和 -b 是可选项标记(使用switch
实现),约束为 -b 选项只有在以前输入 -a 时才有效。
由于
答案 0 :(得分:6)
这可以通过轻微的调整,以两种不同的方式实现:
-b
,你可以创建一个仅允许-a
的解析器,但是你不能坚持认为-a
是第一个,因为optparse-applicative's {{ 1}} combinator没有指定订单。<*>
选项遵循-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')
坚持-a
的{{1}},然后使用*>
代替<*>
来忽略返回值()
和只返回boption
解析器返回的内容,给出选项-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
,仅在命令字符串存在时才有效。您可以使用它来处理像cabal那样的参数,以便cabal install
和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
。
答案 1 :(得分:3)
我担心你不能。这恰恰是Applicative
在Monad
可以处理时无法处理的情况:根据早期结果更改后续操作的结构。在一个应用计算中,&#34;形状&#34;总是需要事先知道;这有一些优点(比如加速这样的数组组合,或为命令行选项提供一个很好的可读帮助屏幕),但这里限制你解析&#34; flat&#34;选项。
optparse-applicative的接口也有Alternative
,但它确实允许依赖解析,尽管是以AndrewC所示的不同方式。