import Data.Semigroup import Data.Monoid hiding ( First, Last ) import System.Environment ( getArgs ) data Flag a = NotSet | Set a deriving (Eq, Show) data Config = Config { verbose :: Flag Bool , options :: [String] } deriving (Eq, Show) defaultConfig :: Config defaultConfig = Config NotSet [] instance Semigroup (Flag a) where _ <> _ = undefined stimes = undefined instance Monoid (Flag a) where mempty = undefined instance Semigroup Config where _ <> _ = undefined stimes = undefined instance Monoid Config where mempty = undefined -- | Table (associative list) containing all known command line arguments. -- | For all arguments, the list stores a function to apply to the full -- | argument string to process the right sight of '=' (if applicable). configTable :: [ (String, String -> Config) ] configTable = [ ("-v", \_ -> defaultConfig { verbose = Set True} ) , ("-q", \_ -> defaultConfig { verbose = Set False} ) , ("-opt", \x -> defaultConfig { options = (:[]) $ argValue x} ) ] where argValue = tail . dropWhile (/= '=') -- | Process a single command line option. -- | Try to look it up in the 'configTable'. If found, the corresponding -- | function is applied, if not, default config is used. processArg :: String -> Config processArg arg = let opt = takeWhile (/= '=') arg in case lookup opt configTable of Nothing -> defaultConfig Just f -> f arg -- | This is entry point of our program. First, we get commandline arguments. -- | Then we process each of them separately with 'processArg'. -- | Last, we 'mconcat' them with our monoid instance to get merged flags. main :: IO () main = getArgs >>= print . mconcat . map processArg