【问题标题】:optparse-applicative: parsing list of pairsoptparse-applicative:解析对列表
【发布时间】:2018-06-15 05:56:37
【问题描述】:

我正在尝试使用 optparse-applicative 解析对列表。解析单个对有效,但使用 many 组合器解析任意多个会失败。

import           Options.Applicative

pairParser = (,) <$> argument str (metavar "s1")
                 <*> argument str (metavar "s2")

testParser p = getParseResult . execParserPure (prefs idm)
  (info (helper <*> p) fullDesc)

main = do
  print $ testParser pairParser ["one", "two"]
  print $ testParser (many pairParser) []
  print $ testParser (many pairParser) ["one", "two"]
  print $ testParser (many pairParser) ["one", "two", "three", "four"]

输出:

Just ("one","two")   <- good
Just []              <- still good
Nothing              <- does not work
Nothing              <- also does not work

有什么想法吗?

【问题讨论】:

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


    【解决方案1】:

    免责声明:我没有使用高级 optparse-applicative 技巧的经验,所以我可能会遗漏一些明显的东西。读者:如果有,请指出。

    您的问题是many 所做的是(在手动描述中)将解析器应用于输入的每个块,在这种情况下,块由单个参数组成,然后收集结果。所以many pairParserpairParser 应用于["one"],然后应用于["two"],两个解析都失败了。既然如此,您可以将execParserPure 替换为以适当方式对参数进行分块并相应调整程序其余部分的函数,或者(我怀疑这是更容易的选择)放弃pairParser 并进行后处理解析后的参数,如:

    pairArgs :: [a] -> [(a, a)]
    pairArgs = noLeftover . foldr pairNext (Nothing, [])
        where
        noLeftover (m, ps) = case m of
            Nothing -> ps
            _       -> []
        pairNext x (m, ps) = case m of
            Just y  -> (Nothing, (x, y) : ps)
            Nothing -> (Just x, ps)
    
    manyPairsParser :: Parser [(String, String)]
    manyPairsParser = pairArgs <$> many (argument str (metavar "s1 s2.."))
    
    GHCi> testParser manyPairsParser []
    Just []
    GHCi> testParser manyPairsParser ["foo"]
    Just []
    GHCi> testParser manyPairsParser ["foo","bar"]
    Just [("foo","bar")]
    GHCi> testParser manyPairsParser ["foo","bar","baz"]
    Just []
    GHCi> testParser manyPairsParser ["foo","bar","baz","quux"]
    Just [("foo","bar"),("baz","quux")]
    

    (请注意,在上面的演示中,我通过返回一个空的对列表来处理失败,并考虑到奇数个参数会导致失败。如果你想要不同的行为,你需要做一些调整.)

    【讨论】:

    • 谢谢!我发现many 的行为确实令人困惑,因为我希望它更像 Parsec ... 是否存在更像 Parsec 样式的命令行解析器?
    • @gedenkt 我不知道。 optparse-applicative 之类的库经过精简和专门处理,可以处理更常见的参数和选项传递用例。顺便说一句,您可能会尝试的另一件事(尽管我没有测试过)是为您的配对指定自定义格式,如{item1,item2} 而不是item1 item2。我相信readme 中的 FluxCapacitor 示例提出了一种使用optparse-applicative 实现这一目标的方法。
    【解决方案2】:

    许多和一些在旧版本的 optparse 中有点过于急切,并且在允许更多选项之前需要在单个选项之后整个构造成功。

    我更改了许多人的逻辑,因此他们更懒惰地使用超过许多选项的选项。可以看到变化和逻辑here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多