2

如果我有以下幾種類型和解析器:哈斯克爾optparse,應用性:解析的具有多個字段的記錄列表

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支持ň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只包含一個字段的情況。

回答

3

如果您使用類型標記Alternative類型的some函數的子分析器,您可以得到您要查找的效果,固然使用稍微不同的命令行語法。

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 [Thing {_name = "test", _mode = Mode1},Thing {_name = "test2", _mode = Mode2}] 

我不明白爲什麼你需要的子分析器和可以」 t對thingParser使用some,但是如果我不得不猜測它會是因爲命令給解析器一個定界符(「thing」參數/命令名)。