如果我有以下类型和解析器:
data Mode =
Mode1
| Mode2
deriving (Show, Eq, Read)
data ThingINeedMulitpleOf =
Thing { _name :: String, _mode :: Mode }
deriving (Show, Eq)
thingParser :: Parser ThingINeedMulitpleOf
thingParser = Thing <$> strArgument (metavar "NAME")
<*> option auto (long "mode" <> metavar "MODE")
我按以下方式构建解析器:
data Config =
Config ThingINeedMulitpleOf ThingINeedMulitpleOf
deriving (Show, Eq)
loadConfig = execParser $ info (Config <$> thingParser <*> thingParser) fullDesc
然后我可以成功解析my-exe Thing1 --mode Mode1 Thing2 --mode Mode2
,但这仅在我需要两个Things
时才有用。
我在尝试更改Config
以支持 n Thing
时遇到问题,即:
data Config =
Config [ThingINeedMulitpleOf]
deriving (Show, Eq)
loadConfig = execParser $ info (Config <$> many thingParser) fullDesc
但我现在无法解析my-exe Thing1 --mode Mode1 Thing2 --mode Mode2
,给我错误Invalid argument 'Thing1'
有趣的是,如果ThingINeedMulitpleOf
只包含一个字段,则此方法有效。
答案 0 :(得分:3)
如果你使用带有Alternative
类型类some
函数的subparser,你可以获得你正在寻找的效果,不可否认,命令行语法略有不同。< / p>
thingSubparser :: Parser ThingINeedMulitpleOf
thingSubparser = subparser $ command "thing" (info thingParser mempty)
loadConfig :: IO Config
loadConfig = execParser $ info (Config <$> some thingSubparser) fullDesc
使用此功能,您可以编写如下命令行:
my-exe thing test --mode Mode1 thing test2 --mode Mode2
产生Config对象:
Config [Thing {_name = "test", _mode = Mode1},Thing {_name = "test2", _mode = Mode2}]
我不太确定你为什么需要subparser并且不能some
使用thingParser
,但如果我不得不猜测它是因为该命令为解析器提供了一个分隔符(&#34; thing&#34;参数/命令名称)。