Отказ от ответственности: У меня нет опыта в использовании продвинутых оппонентов-аппликационных приемов, поэтому я мог бы пропустить что-то очевидное. Читатели: пожалуйста, укажите это, если это так.
Вашей проблема в том, что many
делает (в ручном волнистом описании), чтобы применить анализатор каждого фрагмент входа, с кусками в этом случае, состоящий из отдельных аргументов, а затем собирать результаты. Таким образом, many pairParser
применяет pairParser
к ["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")]
(Обратите внимание, что в демо-версии выше я обработка провала, возвращая пустой список пара, и учитывая, что нечетное число аргументов должно привести к провалу вас. вам нужно будет внести некоторые изменения, если вы хотите по-другому.)
Благодаря! Я считаю, что поведение «много» действительно запутывает, поскольку я ожидал, что он будет работать больше как Parsec ... Существует ли более синтаксический анализатор командной строки в стиле Parsec? – gedenkt
@gedenkt Не знаю, о чем я знаю. Библиотеки, такие как 'optparse-applative', оптимизированы и специализированы для обработки более обычных вариантов использования аргументов и опций. BTW, еще одна вещь, которую вы могли бы попробовать (хотя я ее не тестировал), указывает настраиваемый формат для ваших пар, как в '{item1, item2}' вместо 'item1 item2'. Я считаю, что пример FluxCapacitor в [readme] (https://hackage.haskell.org/package/optparse-applicative-0.11.0.2) предлагает способ достижения этого с помощью 'optparse-applyative'. – duplode