import Data.Monoid import System.Environment ( getArgs ) data Flag a = Set a | NotSet deriving (Eq, Show) data Config = Config { verbose :: Flag Bool , options :: [String] } deriving (Eq, Show) instance Monoid (Flag a) where mempty = NotSet _ `mappend` (Set x) = Set x x `mappend` NotSet = x instance Monoid Config where mempty = defaultConfig c1 `mappend` c2 = Config (verbose c1 `mappend` verbose c2) (options c1 `mappend` options c2) defaultConfig :: Config defaultConfig = Config NotSet [] configTable :: [ (String, String -> Config) ] configTable = [ ("-v", \_ -> defaultConfig { verbose = Set True} ) , ("-q", \_ -> defaultConfig { verbose = Set False} ) , ("-opt", \x -> defaultConfig { options = (:[]) . tail $ dropWhile (/= '=') x} ) ] 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, we get commandline arguments, process -- each of them separately with 'processArg' and then 'mconcat' them with our -- monoid instance to get merged flags main :: IO () main = getArgs >>= print . mconcat . map processArg