Haskell, unnamed command line arguments for optpar

2019-07-04 13:36发布

问题:

I'm using optparse-generic to parse the command line arguments of a program called example. I have a datatype with named fields (record syntax). For example:

data Example = Example { foo :: Int, bar :: String } deriving (Generic, Show)

This generates a program which can be called as follows:

./example --foo 42 --bar "baz"

How can I tell optparse-generic that bar should be an unnamed, mandatory, positional command line argument. That means, I don't want to type --bar when I call example. For example, I want to call example the following:

./example --foo 42 "baz"

回答1:

optparse-generic does not support generating such a parser from a single data type definition since Haskell does not support records with both labeled and unlabeled fields.

However, what you can do is generate one data type for all the labeled fields and one type for the unlabeled fields and then combine them using Applicative operations, like this:

data Labeled = Labeled { foo :: Int } deriving (Generic, Show)

instance ParseRecord Labeled

data Unlabeled = Unlabeled String deriving (Generic, Show)

instance ParseRecord Unlabeled

data Mixed = Mixed Labeled Unlabeled deriving (Show)

instance ParseRecord Mixed where
    parseRecord = Mixed <$> parseRecord <*> parseRecord