的类型option
是:
option :: ReadM a -> Mod OptionFields a -> Parser a
ReadM
,反过来,是“选项阅读器使用的'ReaderT String except'上的新类型”。由于在引擎盖下使用,当您将它与option
您在此处所做的实例一起使用时...ReaderT
Applicative
ReadM
ROI <$> auto <*> auto <*> auto <*> auto
... 为四个auto
解析器中的每一个提供相同且完整的输入字符串,因为这就是阅读器/函数应用程序实例的工作方式。
如果您希望将由空格分隔的值解析为单个ROI
,则需要编写自定义解析器。这是一个不是特别整洁的尝试,围绕eitherReader
. 请注意,这将要求值在引号 ( --roi "1 2 3 4"
) 内,以便将它们作为单个字符串接收。Cubic 的回答提出了一种替代方法,它使用逗号分隔的值代替 ( --roi 1,2,3,4
)。
import Text.Read (readEither)
-- etc.
roi :: Parser (Maybe ROI)
roi = optional
$ option (eitherReader $ \inp -> case traverse readEither (words inp) of
Right [x, y, z, w] -> Right (ROI x y z w)
Right _ -> Left "ROI requires exactly 4 values"
Left _ -> Left "ROI requires integer values")
$ long "roi" <> metavar "ROI" <> help "Only process selected region of interest"
成功和失败模式:
GHCi> execParserPure defaultPrefs (info roi mempty) ["--roi","1 2 3 4"]
Success (Just (ROI 1 2 3 4))
GHCi> execParserPure defaultPrefs (info roi mempty) ["--roi","1 2 3"]
Failure (ParserFailure (option --roi: ROI requires exactly 4 values
Usage: <program> [--roi ROI],ExitFailure 1,80))
GHCi> execParserPure defaultPrefs (info roi mempty) ["--roi","1 2 foo 4"]
Failure (ParserFailure (option --roi: ROI requires integer values
Usage: <program> [--roi ROI],ExitFailure 1,80))