如何在 Options.Applicative 中为互斥标志编码

Bre*_*ugh 3 haskell optparse-applicative

我是 Haskell 新手。作为一项学习练习,我正在尝试将我的一个 Rust 程序移植到 Haskell。在 Rust 中,我使用了令人惊叹的clap包,并且被认为是Options.Applicative一个好看的替代品。下面是一个例子:

import Options.Applicative
import Data.Semigroup ((<>))

data Sample = Sample
  { tod        :: Bool
  , pmc        :: Bool
  , tai        :: Bool
  }

sample :: Parser Sample
sample = Sample
      <$>  switch
          ( long "tod"
            <> short 'o'
            <> help "Convert from TOD" )
      <*> switch
          ( long "pmc"
            <> short 'p'
            <> help "Convert from PMC" ) 
      <*> switch
          ( long "tai"
            <> short 't'
            <> help "Set TAI mode" )

main :: IO ()
main = greet =<< execParser opts
  where
    opts = info (sample <**> helper) ( fullDesc )
greet :: Sample -> IO ()
greet (Sample a b c) = print [a,b,c]
Run Code Online (Sandbox Code Playgroud)

走到这一步,我撞到了一堵砖墙。我需要使“tod”和“pmc”标志互斥。README 包中有一个使用 <|> 的示例,但它不适用于布尔标志,我不知道如何转换它。

请问有人可以帮忙吗?

Dan*_*ner 9

制作其中之一pmctod成为计算值,并仅存储另一个。

data Sample = Sample
    { tod :: Bool
    , tai :: Bool
    }

pmc = not . tod

sample = Sample
    <$> (   flag' True  (short 'o')
        <|> flag' False (short 'p')
        <|> pure True -- what do you want to do if they specify neither?
        )
    <*> switch (short 't')
Run Code Online (Sandbox Code Playgroud)

或者也许实际上存在三种操作模式。然后,使双方todpmc计算领域。

data Mode = TOD | PMC | Other deriving Eq

data Sample = Sample
    { mode :: Mode
    , tai :: Bool
    }

tod = (TOD==) . mode
pmc = (PMC==) . mode

sample = Sample
    <$> (   flag' TOD (short 'o')
        <|> flag' PMC (short 'p')
        <|> pure Other
        )
    <*> switch (short 't')
Run Code Online (Sandbox Code Playgroud)