haskell optparse-applicative:解析具有多个字段的记录列表

时间:2016-06-10 02:36:03

标签: parsing haskell command-line-arguments applicative command-line-parsing

如果我有以下类型和解析器:

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只包含一个字段,则此方法有效。

1 个答案:

答案 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;参数/命令名称)。