data Config = Config {
a :: Bool,
b :: Type1,
c :: Type2
}
pA :: Parser Bool
pB :: Parser Type1
pC :: Parser Type2
pConfig :: Parser Config
pConfig = Config <$> pA <*> pB <*> pC
opts :: ParserInfo Config
opts = info (pConfig <**> helper)
(fullDesc <> progDesc "My CLI" <> header "CLI executable")
main :: IO()
main = do
(Config a b c) <- execParser opts
-- Populate a default config using a b c values
Is it possible to parse a product type partially? Config is a product type with member a, b and c and assume this comes from a library, so I cannot redefine this. I only want to parse a and b without caring about c. But, since a "Parser Config" can only have a construction like below
Config <$> pA <*> pB <*> pC
due to being a product type, if I do not give a "pC" it errors out. How to correctly handle this scenario?
The Config <$> pA <*> pB <*> pC
notation doesn’t care that Config
is a constructor; you could have used any function of type Bool -> Type1 -> Type2 -> Config
. If you don’t want to parse a Type2
, you could use any function of type Bool -> Type1 -> Config
.
config' :: Bool -> Type1 -> Config
config' a b c = Config a b someDefaultType2
pConfig :: Parser Config
pConfig = config' <$> pA <*> pB
Equivalently, you stick with the Config
constructor but connect a pure
value instead of a parser to its third argument.
pConfig :: Parser Config
pConfig = Config <$> pA <*> pB <*> pure someDefaultType2
(Either way, you do need to have some way of providing a value of Type2
, if you want to get a Config
out.)