5

慎重に作成されたパーサーが、スローした文字列を解析できないことがわかりました。

roi :: Parser (Maybe ROI)
roi = optional $ option (ROI <$> auto <*> auto <*> auto <*> auto)
               $ long "roi" <> metavar "ROI" <> help "Only process selected region of interest"

どこROI = ROI Int Int Int Int

それが重要な場合は、上位のパーサーにネストされています

options :: Parser Opts
options = Opts <$> input <*> output <*> roi <*> startT <*> endT  

Opts適切な ADT です。

ここで、roiパーサーが次のような式を解析すると仮定しまし--roi 1 2 3 4たが、失敗しInvalid argument '128'て使用法メッセージが表示されます。

--roi 1代わりに解析しますが、返しますJust (ROI 1 1 1 1)

これを機能させる方法はありますか?

4

2 に答える 2

7

オプションが複数の引数を消費することになっているとは思いません。少なくとも、それをどのように実装するかはわかりません。その考えから離れて、ROI オプションを単一の引数に入れ、次のような構文を使用することをお勧めします--roi 1,2,3,4

そのためにカスタムリーダーを実装するだけで済みます。これを行う方法の例を次に示します。

module Main where

import Options.Applicative

data ROI = ROI Int Int Int Int
  deriving Show

-- didn't remember what this function was called, don't use this
splitOn :: Eq a => a -> [a] -> [[a]]
splitOn sep (x:xs) | sep==x     = [] : splitOn sep xs
                   | otherwise = let (xs':xss) = splitOn sep xs in (x:xs'):xss
splitOn _ [] = [[]]

roiReader :: ReadM ROI
roiReader = do
  o <- str
  -- no error checking, don't actually do this
  let [a,b,c,d] = map read $ splitOn ',' o
  return $ ROI a b c d

roiParser :: Parser ROI
roiParser = option roiReader (long "roi")

main :: IO ()
main = execParser opts >>= print where
  opts = info (helper <*> roiParser) fullDesc
于 2016-12-16T14:19:33.873 に答える