【发布时间】:2021-08-18 22:25:15
【问题描述】:
假设我有以下递归定义的 ADT
data GraphType = Character | Colour | Nested GraphType deriving (Show)
我可以为这个结构定义一个解析器(使用optparse-applicative,导入为OA),递归方式如下:
typeParser :: OA.Parser GraphType
typeParser =
OA.flag' Colour (OA.long "colour")
<|> OA.flag' Character (OA.long "character")
<|> (OA.flag' Nested (OA.long "nested") <*> typeParser)
这让我可以传递参数,例如
-
--colour获取Colour的值 -
--nested --colour获得Nested Colour的值 -
--nested --colour获得Nested (Nested Colour)的值 - 等等
不幸的是,如果我尝试为解析器生成帮助文本,它会失败。
这在一定程度上是有道理的,因为解析器的“结构”是无限大的。
但是,我很乐观地认为可能会有某种解决方法,例如转换内部 typeParser,这样我们就不会尝试为其生成帮助文本。
可以对此解析器进行的最小修改以使其保留有效的帮助文本?
除了不能生成帮助文本之外,如果我想修改解析器为以下(添加一个默认值,还允许--nested自己解析为Nested Character),这个也会挂掉,而不是达到默认值:
typeParser :: OA.Parser GraphType
typeParser =
OA.flag' Colour (OA.long "colour")
<|> OA.flag' Character (OA.long "character")
<|> (OA.flag' Nested (OA.long "nested") <*> typeParser)
<|> pure Character
通过将解析器更改为以下内容,我已经能够解决该问题
typeParser :: OA.Parser GraphType
typeParser = iter Nested <$> nestDepthParser <*> unnestedParser
where
iter f 0 v = v
iter f n v = iter f (n - 1) (f v)
nestDepthParser = OA.option OA.auto (OA.long "nest") <|> pure 0
unnestedParser =
OA.flag' Colour (OA.long "colour")
<|> OA.flag' Character (OA.long "character")
<|> pure Character
要在此解析器中指定 Nested (Nested Colour) 的值,您需要传递 --nest 2 --colour。
这可行,但并不理想,因为我真的很喜欢“多个--nesting 参数”的命令风格。
【问题讨论】:
标签: haskell command-line-arguments lazy-evaluation applicative optparse-applicative