如何在haskell options.applicative中为记录类型进行模式匹配?

时间:2016-07-11 05:25:13

标签: haskell pattern-matching

我使用Options.Applicative来处理haskell命令行,我的选项记录类型如下:

data Options = Options {  xml :: String
                          ,eut :: String
                       } deriving (Show)

options :: Parser Options
options = Options
              <$> strOption ( short 'x'
                              <> long "xml"
                              <> metavar "XMLFILE"
                              <> value []
                              <> help "GCCXML file for parsing" )
              <*> strOption ( short 'e'
                              <> long "eut"
                              <> metavar "PATH_2_EUT"
                              <> value []
                              <> help "EUT Json filepath for parsing" )

然后在我的haskell主代码中,我有:

main :: IO ()
main = do
  options <- execParser parseOpts
  case options of
    Options {xml = [], eut = []} -> putStrLn "use -h to print usage info"
    -- xml option
    Options {xml = _, eut = []} -> parseXML $ xml options
    -- eut option
    Options {xml = [], eut = _} -> genMeta $ eut options
    -- no matching
    _ -> putStrLn "use -h to print usage info"
  where
    parseOpts = info (helper <*> options)
      ( fullDesc
        <> progDesc "Given GCCXML file, generate EUT json and test meta files"
        <> header "map2meta - Generate test meta files" )

我的目的是为"-x""-e"进行处理。我通过使用模式Options {xml = _, eut = []}来匹配命令行具有"-x"但没有"-e"的情况来实现此目的,而Options {xml = [], eut = _ }则匹配命令行具有"-e"的情况但没有"-x"。但是,当我在没有任何选项的情况下运行程序时,似乎Options {xml = _ , eut = [] }匹配。所以我添加了Options {xml = [], eut = []}来拦截这种情况。我认为占位符'_'实际上可以用来匹配'[]',虽然我希望它只匹配'something'而不是空字符串。因此,我的第一个问题是如何创建一个匹配非空字符串的模式?

我的第二个问题是如何添加代码以打印出使用信息?现在,它只在我使用"-h"时打印出来。我想在命令行中没有提供选项时打印它。

1 个答案:

答案 0 :(得分:1)

由于String只是[Char]的类型同义词,因此您可以使用模式_:_匹配非空字符串,即带有头元素的非空列表{{ 1}}(无论如何)和尾部列表_(无论如何)。

所以你可以有三种情况:

  • _Options {xml = _:_, eut = []}已设置,xml未设置
  • eutOptions {xml = [], eut = _:_}已设置,eut未设置
  • xml:所有其余的(两者都未设置,或两者都是)

或者,您可以选择multi-way if

_