summaryrefslogtreecommitdiff
path: root/src-3.0/GF/Infra/Option.hs
diff options
context:
space:
mode:
authoraarne <aarne@cs.chalmers.se>2008-06-25 16:54:35 +0000
committeraarne <aarne@cs.chalmers.se>2008-06-25 16:54:35 +0000
commite9e80fc389365e24d4300d7d5390c7d833a96c50 (patch)
treef0b58473adaa670bd8fc52ada419d8cad470ee03 /src-3.0/GF/Infra/Option.hs
parentb96b36f43de3e2f8b58d5f539daa6f6d47f25870 (diff)
changed names of resource-1.3; added a note on homepage on release
Diffstat (limited to 'src-3.0/GF/Infra/Option.hs')
-rw-r--r--src-3.0/GF/Infra/Option.hs549
1 files changed, 0 insertions, 549 deletions
diff --git a/src-3.0/GF/Infra/Option.hs b/src-3.0/GF/Infra/Option.hs
deleted file mode 100644
index 380cb3af7..000000000
--- a/src-3.0/GF/Infra/Option.hs
+++ /dev/null
@@ -1,549 +0,0 @@
-module GF.Infra.Option
- (
- -- * Option types
- Options, ModuleOptions,
- Flags(..), ModuleFlags(..),
- Mode(..), Phase(..), Verbosity(..), Encoding(..), OutputFormat(..),
- SISRFormat(..), Optimization(..),
- Dump(..), Printer(..), Recomp(..),
- -- * Option parsing
- parseOptions, parseModuleOptions,
- -- * Option pretty-printing
- moduleOptionsGFO,
- -- * Option manipulation
- addOptions, concatOptions, noOptions,
- moduleOptions,
- addModuleOptions, concatModuleOptions, noModuleOptions,
- helpMessage,
- -- * Checking specific options
- flag, moduleFlag,
- -- * Setting specific options
- setOptimization,
- -- * Convenience methods for checking options
- verbAtLeast, dump
- ) where
-
-import Control.Monad
-import Data.Char (toLower)
-import Data.List
-import Data.Maybe
-import GF.Infra.GetOpt
---import System.Console.GetOpt
-import System.FilePath
-
-import GF.Data.ErrM
-
-import Data.Set (Set)
-import qualified Data.Set as Set
-
-
-
-
-usageHeader :: String
-usageHeader = unlines
- ["Usage: gfc [OPTIONS] [FILE [...]]",
- "",
- "How each FILE is handled depends on the file name suffix:",
- "",
- ".gf Normal or old GF source, will be compiled.",
- ".gfo Compiled GF source, will be loaded as is.",
- ".gfe Example-based GF source, will be converted to .gf and compiled.",
- ".ebnf Extended BNF format, will be converted to .gf and compiled.",
- ".cf Context-free (BNF) format, will be converted to .gf and compiled.",
- "",
- "If multiple FILES are given, they must be normal GF source, .gfo or .gfe files.",
- "For the other input formats, only one file can be given.",
- "",
- "Command-line options:"]
-
-
-helpMessage :: String
-helpMessage = usageInfo usageHeader optDescr
-
-
--- FIXME: do we really want multi-line errors?
-errors :: [String] -> Err a
-errors = fail . unlines
-
--- Types
-
-data Mode = ModeVersion | ModeHelp | ModeInteractive | ModeCompiler
- deriving (Show,Eq,Ord)
-
-data Verbosity = Quiet | Normal | Verbose | Debug
- deriving (Show,Eq,Ord,Enum,Bounded)
-
-data Phase = Preproc | Convert | Compile | Link
- deriving (Show,Eq,Ord)
-
-data Encoding = UTF_8 | ISO_8859_1 | CP_1251
- deriving (Show,Eq,Ord)
-
-data OutputFormat = FmtPGF
- | FmtJavaScript
- | FmtHaskell
- | FmtHaskell_GADT
- | FmtBNF
- | FmtSRGS_XML
- | FmtSRGS_ABNF
- | FmtJSGF
- | FmtGSL
- | FmtVoiceXML
- | FmtSLF
- | FmtRegExp
- | FmtFA
- deriving (Eq,Ord)
-
-data SISRFormat =
- -- | SISR Working draft 1 April 2003
- -- <http://www.w3.org/TR/2003/WD-semantic-interpretation-20030401/>
- SISR_WD20030401
- | SISR_1_0
- deriving (Show,Eq,Ord)
-
-data Optimization = OptStem | OptCSE | OptExpand | OptParametrize | OptValues
- deriving (Show,Eq,Ord)
-
-data Warning = WarnMissingLincat
- deriving (Show,Eq,Ord)
-
-data Dump = DumpRebuild | DumpExtend | DumpRename | DumpTypeCheck | DumpRefresh | DumpOptimize | DumpCanon
- deriving (Show,Eq,Ord)
-
--- | Pretty-printing options
-data Printer = PrinterStrip -- ^ Remove name qualifiers.
- deriving (Show,Eq,Ord)
-
-data Recomp = AlwaysRecomp | RecompIfNewer | NeverRecomp
- deriving (Show,Eq,Ord)
-
-data ModuleFlags = ModuleFlags {
- optName :: Maybe String,
- optAbsName :: Maybe String,
- optCncName :: Maybe String,
- optResName :: Maybe String,
- optPreprocessors :: [String],
- optEncoding :: Encoding,
- optOptimizations :: Set Optimization,
- optLibraryPath :: [FilePath],
- optStartCat :: Maybe String,
- optSpeechLanguage :: Maybe String,
- optLexer :: Maybe String,
- optUnlexer :: Maybe String,
- optErasing :: Bool,
- optBuildParser :: Bool,
- optWarnings :: [Warning],
- optDump :: [Dump]
- }
- deriving (Show)
-
-data Flags = Flags {
- optMode :: Mode,
- optStopAfterPhase :: Phase,
- optVerbosity :: Verbosity,
- optShowCPUTime :: Bool,
- optEmitGFO :: Bool,
- optGFODir :: FilePath,
- optOutputFormats :: [OutputFormat],
- optSISR :: Maybe SISRFormat,
- optOutputFile :: Maybe FilePath,
- optOutputDir :: Maybe FilePath,
- optRecomp :: Recomp,
- optPrinter :: [Printer],
- optProb :: Bool,
- optRetainResource :: Bool,
- optModuleFlags :: ModuleFlags
- }
- deriving (Show)
-
-newtype Options = Options (Flags -> Flags)
-
-instance Show Options where
- show (Options o) = show (o defaultFlags)
-
-newtype ModuleOptions = ModuleOptions (ModuleFlags -> ModuleFlags)
-
--- Option parsing
-
-parseOptions :: [String] -> Err (Options, [FilePath])
-parseOptions args
- | not (null errs) = errors errs
- | otherwise = do opts <- liftM concatOptions $ sequence optss
- return (opts, files)
- where (optss, files, errs) = getOpt RequireOrder optDescr args
-
-parseModuleOptions :: [String] -> Err ModuleOptions
-parseModuleOptions args
- | not (null errs) = errors errs
- | not (null files) = errors $ map ("Non-option among module options: " ++) files
- | otherwise = liftM concatModuleOptions $ sequence flags
- where (flags, files, errs) = getOpt RequireOrder moduleOptDescr args
-
--- Showing options
-
--- | Pretty-print the module options that are preserved in .gfo files.
-moduleOptionsGFO :: ModuleOptions -> [(String,String)]
-moduleOptionsGFO (ModuleOptions o) =
- maybe [] (\x -> [("language",x)]) (optSpeechLanguage mfs)
- ++ maybe [] (\x -> [("startcat",x)]) (optStartCat mfs)
--- ++ maybe [] (\x -> [("coding", e2s x)]) (Just (optEncoding mfs))
- ++ (if optErasing mfs then [("erasing","on")] else [])
- where
- mfs = o defaultModuleFlags
- e2s e = maybe [] id $ lookup e [(s,e) | (e,s) <- encodings]
-
--- Option manipulation
-
-noOptions :: Options
-noOptions = Options id
-
-addOptions :: Options -- ^ Existing options.
- -> Options -- ^ Options to add (these take preference).
- -> Options
-addOptions (Options o1) (Options o2) = Options (o2 . o1)
-
-concatOptions :: [Options] -> Options
-concatOptions = foldr addOptions noOptions
-
-moduleOptions :: ModuleOptions -> Options
-moduleOptions (ModuleOptions f) = Options (\o -> o { optModuleFlags = f (optModuleFlags o) })
-
-addModuleOptions :: ModuleOptions -- ^ Existing options.
- -> ModuleOptions -- ^ Options to add (these take preference).
- -> ModuleOptions
-addModuleOptions (ModuleOptions o1) (ModuleOptions o2) = ModuleOptions (o2 . o1)
-
-concatModuleOptions :: [ModuleOptions] -> ModuleOptions
-concatModuleOptions = foldr addModuleOptions noModuleOptions
-
-noModuleOptions :: ModuleOptions
-noModuleOptions = ModuleOptions id
-
-flag :: (Flags -> a) -> Options -> a
-flag f (Options o) = f (o defaultFlags)
-
-moduleFlag :: (ModuleFlags -> a) -> Options -> a
-moduleFlag f = flag (f . optModuleFlags)
-
-modifyFlags :: (Flags -> Flags) -> Options
-modifyFlags = Options
-
-modifyModuleFlags :: (ModuleFlags -> ModuleFlags) -> Options
-modifyModuleFlags = moduleOptions . ModuleOptions
-
-
-{-
-
-parseModuleFlags :: Options -> [(String,Maybe String)] -> Err ModuleOptions
-parseModuleFlags opts flags =
- mapM (uncurry (findFlag moduleOptDescr)) flags >>= foldM (flip ($)) (optModuleOptions opts)
-
-findFlag :: Monad m => [OptDescr a] -> String -> Maybe String -> m a
-findFlag opts n mv =
- case filter (`flagMatches` n) opts of
- [] -> fail $ "Unknown option: " ++ n
- [opt] -> flagValue opt n mv
- _ -> fail $ n ++ " matches multiple options."
-
-flagMatches :: OptDescr a -> String -> Bool
-flagMatches (Option cs ss _ _) n = n `elem` (map (:[]) cs ++ ss)
-
-flagValue :: Monad m => OptDescr a -> String -> Maybe String -> m a
-flagValue (Option _ _ arg _) n mv =
- case (arg, mv) of
- (NoArg x, Nothing) -> return x
- (NoArg _, Just _ ) -> fail $ "Option " ++ n ++ " does not take a value."
- (ReqArg _ _, Nothing) -> fail $ "Option " ++ n ++ " requires a value."
- (ReqArg f _, Just x ) -> return (f x)
- (OptArg f _, mx ) -> return (f mx)
-
--}
-
--- Default options
-
-defaultModuleFlags :: ModuleFlags
-defaultModuleFlags = ModuleFlags {
- optName = Nothing,
- optAbsName = Nothing,
- optCncName = Nothing,
- optResName = Nothing,
- optPreprocessors = [],
- optEncoding = ISO_8859_1,
- optOptimizations = Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize,OptValues],
- optLibraryPath = [],
- optStartCat = Nothing,
- optSpeechLanguage = Nothing,
- optLexer = Nothing,
- optUnlexer = Nothing,
- optErasing = False,
- optBuildParser = True,
- optWarnings = [],
- optDump = []
- }
-
-defaultFlags :: Flags
-defaultFlags = Flags {
- optMode = ModeInteractive,
- optStopAfterPhase = Compile,
- optVerbosity = Normal,
- optShowCPUTime = False,
- optEmitGFO = True,
- optGFODir = ".",
- optOutputFormats = [FmtPGF],
- optSISR = Nothing,
- optOutputFile = Nothing,
- optOutputDir = Nothing,
- optRecomp = RecompIfNewer,
- optPrinter = [],
- optProb = False,
- optRetainResource = False,
- optModuleFlags = defaultModuleFlags
- }
-
--- Option descriptions
-
-moduleOptDescr :: [OptDescr (Err ModuleOptions)]
-moduleOptDescr =
- [
- Option ['n'] ["name"] (ReqArg name "NAME")
- (unlines ["Use NAME as the name of the output. This is used in the output file names, ",
- "with suffixes depending on the formats, and, when relevant, ",
- "internally in the output."]),
- Option [] ["abs"] (ReqArg absName "NAME")
- ("Use NAME as the name of the abstract syntax module generated from "
- ++ "a grammar in GF 1 format."),
- Option [] ["cnc"] (ReqArg cncName "NAME")
- ("Use NAME as the name of the concrete syntax module generated from "
- ++ "a grammar in GF 1 format."),
- Option [] ["res"] (ReqArg resName "NAME")
- ("Use NAME as the name of the resource module generated from "
- ++ "a grammar in GF 1 format."),
- Option ['i'] [] (ReqArg addLibDir "DIR") "Add DIR to the library search path.",
- Option [] ["path"] (ReqArg setLibPath "DIR:DIR:...") "Set the library search path.",
- Option [] ["preproc"] (ReqArg preproc "CMD")
- (unlines ["Use CMD to preprocess input files.",
- "Multiple preprocessors can be used by giving this option multiple times."]),
- Option [] ["coding"] (ReqArg coding "ENCODING")
- ("Character encoding of the source grammar, ENCODING = "
- ++ concat (intersperse " | " (map fst encodings)) ++ "."),
- Option [] ["erasing"] (onOff erasing False) "Generate erasing grammar (default off).",
- Option [] ["parser"] (onOff parser True) "Build parser (default on).",
- Option [] ["startcat"] (ReqArg startcat "CAT") "Grammar start category.",
- Option [] ["language"] (ReqArg language "LANG") "Set the speech language flag to LANG in the generated grammar.",
- Option [] ["lexer"] (ReqArg lexer "LEXER") "Use lexer LEXER.",
- Option [] ["unlexer"] (ReqArg unlexer "UNLEXER") "Use unlexer UNLEXER.",
- Option [] ["optimize"] (ReqArg optimize "OPT")
- "Select an optimization package. OPT = all | values | parametrize | none",
- Option [] ["stem"] (onOff (toggleOptimize OptStem) True) "Perform stem-suffix analysis (default on).",
- Option [] ["cse"] (onOff (toggleOptimize OptCSE) True) "Perform common sub-expression elimination (default on).",
- dumpOption "rebuild" DumpRebuild,
- dumpOption "extend" DumpExtend,
- dumpOption "rename" DumpRename,
- dumpOption "tc" DumpTypeCheck,
- dumpOption "refresh" DumpRefresh,
- dumpOption "opt" DumpOptimize,
- dumpOption "canon" DumpCanon
- ]
- where
- name x = set $ \o -> o { optName = Just x }
- absName x = set $ \o -> o { optAbsName = Just x }
- cncName x = set $ \o -> o { optCncName = Just x }
- resName x = set $ \o -> o { optResName = Just x }
- addLibDir x = set $ \o -> o { optLibraryPath = x:optLibraryPath o }
- setLibPath x = set $ \o -> o { optLibraryPath = splitInModuleSearchPath x }
- preproc x = set $ \o -> o { optPreprocessors = optPreprocessors o ++ [x] }
- coding x = case lookup x encodings of
- Just c -> set $ \o -> o { optEncoding = c }
- Nothing -> fail $ "Unknown character encoding: " ++ x
- erasing x = set $ \o -> o { optErasing = x }
- parser x = set $ \o -> o { optBuildParser = x }
- startcat x = set $ \o -> o { optStartCat = Just x }
- language x = set $ \o -> o { optSpeechLanguage = Just x }
- lexer x = set $ \o -> o { optLexer = Just x }
- unlexer x = set $ \o -> o { optUnlexer = Just x }
-
- optimize x = case lookup x optimizationPackages of
- Just p -> set $ \o -> o { optOptimizations = p }
- Nothing -> fail $ "Unknown optimization package: " ++ x
-
- toggleOptimize x b = set $ setOptimization' x b
-
- dumpOption s d = Option [] ["dump-"++s] (NoArg (set $ \o -> o { optDump = d:optDump o})) ("Dump output of the " ++ s ++ " phase.")
-
- set = return . ModuleOptions
-
-optDescr :: [OptDescr (Err Options)]
-optDescr =
- [
- Option ['?','h'] ["help"] (NoArg (mode ModeHelp)) "Show help message.",
- Option ['V'] ["version"] (NoArg (mode ModeVersion)) "Display GF version number.",
- Option ['v'] ["verbose"] (OptArg verbosity "N") "Set verbosity (default 1). -v alone is the same as -v 2.",
- Option ['q','s'] ["quiet"] (NoArg (verbosity (Just "0"))) "Quiet, same as -v 0.",
- Option [] ["batch"] (NoArg (mode ModeCompiler)) "Run in batch compiler mode.",
- Option [] ["interactive"] (NoArg (mode ModeInteractive)) "Run in interactive mode (default).",
- Option ['E'] [] (NoArg (phase Preproc)) "Stop after preprocessing (with --preproc).",
- Option ['C'] [] (NoArg (phase Convert)) "Stop after conversion to .gf.",
- Option ['c'] [] (NoArg (phase Compile)) "Stop after compiling to .gfo (default) .",
- Option [] ["make"] (NoArg (phase Link)) "Build .pgf file and other output files.",
- Option [] ["cpu"] (NoArg (cpu True)) "Show compilation CPU time statistics.",
- Option [] ["no-cpu"] (NoArg (cpu False)) "Don't show compilation CPU time statistics (default).",
- Option [] ["emit-gfo"] (NoArg (emitGFO True)) "Create .gfo files (default).",
- Option [] ["no-emit-gfo"] (NoArg (emitGFO False)) "Do not create .gfo files.",
- Option [] ["gfo-dir"] (ReqArg gfoDir "DIR") "Directory to put .gfo files in (default = '.').",
- Option ['f'] ["output-format"] (ReqArg outFmt "FMT")
- (unlines ["Output format. FMT can be one of:",
- "Multiple concrete: pgf (default), gar, js, ...",
- "Single concrete only: cf, bnf, lbnf, gsl, srgs_xml, srgs_abnf, ...",
- "Abstract only: haskell, ..."]),
- Option [] ["sisr"] (ReqArg sisrFmt "FMT")
- (unlines ["Include SISR tags in generated speech recognition grammars.",
- "FMT can be one of: old, 1.0"]),
- Option ['o'] ["output-file"] (ReqArg outFile "FILE")
- "Save output in FILE (default is out.X, where X depends on output format.",
- Option ['D'] ["output-dir"] (ReqArg outDir "DIR")
- "Save output files (other than .gfc files) in DIR.",
- Option [] ["src","force-recomp"] (NoArg (recomp AlwaysRecomp))
- "Always recompile from source.",
- Option [] ["gfo","recomp-if-newer"] (NoArg (recomp RecompIfNewer))
- "(default) Recompile from source if the source is newer than the .gfo file.",
- Option [] ["gfo","no-recomp"] (NoArg (recomp NeverRecomp))
- "Never recompile from source, if there is already .gfo file.",
- Option [] ["strip"] (NoArg (printer PrinterStrip))
- "Remove name qualifiers when pretty-printing.",
- Option [] ["retain"] (NoArg (set $ \o -> o { optRetainResource = True })) "Retain opers.",
- Option [] ["prob"] (NoArg (prob True)) "Read probabilities from '--# prob' pragmas."
- ] ++ map (fmap (liftM moduleOptions)) moduleOptDescr
- where phase x = set $ \o -> o { optStopAfterPhase = x }
- mode x = set $ \o -> o { optMode = x }
- verbosity mv = case mv of
- Nothing -> set $ \o -> o { optVerbosity = Verbose }
- Just v -> case readMaybe v >>= toEnumBounded of
- Just i -> set $ \o -> o { optVerbosity = i }
- Nothing -> fail $ "Bad verbosity: " ++ show v
- cpu x = set $ \o -> o { optShowCPUTime = x }
- emitGFO x = set $ \o -> o { optEmitGFO = x }
- gfoDir x = set $ \o -> o { optGFODir = x }
- outFmt x = readOutputFormat x >>= \f ->
- set $ \o -> o { optOutputFormats = optOutputFormats o ++ [f] }
- sisrFmt x = case x of
- "old" -> set $ \o -> o { optSISR = Just SISR_WD20030401 }
- "1.0" -> set $ \o -> o { optSISR = Just SISR_1_0 }
- _ -> fail $ "Unknown SISR format: " ++ show x
- outFile x = set $ \o -> o { optOutputFile = Just x }
- outDir x = set $ \o -> o { optOutputDir = Just x }
- recomp x = set $ \o -> o { optRecomp = x }
- printer x = set $ \o -> o { optPrinter = x : optPrinter o }
- prob x = set $ \o -> o { optProb = x }
-
- set = return . Options
-
-outputFormats :: [(String,OutputFormat)]
-outputFormats =
- [("pgf", FmtPGF),
- ("js", FmtJavaScript),
- ("haskell", FmtHaskell),
- ("haskell_gadt", FmtHaskell_GADT),
- ("bnf", FmtBNF),
- ("srgs_xml", FmtSRGS_XML),
- ("srgs_abnf", FmtSRGS_ABNF),
- ("jsgf", FmtJSGF),
- ("gsl", FmtGSL),
- ("vxml", FmtVoiceXML),
- ("slf", FmtSLF),
- ("regexp", FmtRegExp),
- ("fa", FmtFA)]
-
-instance Show OutputFormat where
- show = lookupShow outputFormats
-
-instance Read OutputFormat where
- readsPrec = lookupReadsPrec outputFormats
-
-optimizationPackages :: [(String, Set Optimization)]
-optimizationPackages =
- [("all_subs", Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize,OptValues]), -- deprecated
- ("all", Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize,OptValues]),
- ("values", Set.fromList [OptStem,OptCSE,OptExpand,OptValues]),
- ("parametrize", Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize]),
- ("none", Set.fromList [OptStem,OptCSE,OptExpand]),
- ("noexpand", Set.fromList [OptStem,OptCSE])]
-
-encodings :: [(String,Encoding)]
-encodings =
- [("utf8", UTF_8),
- ("cp1251", CP_1251),
- ("latin1", ISO_8859_1)
- ]
-
-lookupShow :: Eq a => [(String,a)] -> a -> String
-lookupShow xs z = fromMaybe "lookupShow" $ lookup z [(y,x) | (x,y) <- xs]
-
-lookupReadsPrec :: [(String,a)] -> Int -> ReadS a
-lookupReadsPrec xs _ s = [(z,rest) | (x,rest) <- lex s, (y,z) <- xs, y == x]
-
-onOff :: Monad m => (Bool -> m a) -> Bool -> ArgDescr (m a)
-onOff f def = OptArg g "[on,off]"
- where g ma = maybe (return def) readOnOff ma >>= f
- readOnOff x = case map toLower x of
- "on" -> return True
- "off" -> return False
- _ -> fail $ "Expected [on,off], got: " ++ show x
-
-readOutputFormat :: Monad m => String -> m OutputFormat
-readOutputFormat s =
- maybe (fail $ "Unknown output format: " ++ show s) return $ lookup s outputFormats
-
--- FIXME: this is a copy of the function in GF.Devel.UseIO.
-splitInModuleSearchPath :: String -> [FilePath]
-splitInModuleSearchPath s = case break isPathSep s of
- (f,_:cs) -> f : splitInModuleSearchPath cs
- (f,_) -> [f]
- where
- isPathSep :: Char -> Bool
- isPathSep c = c == ':' || c == ';'
-
---
--- * Convenience functions for checking options
---
-
-verbAtLeast :: Options -> Verbosity -> Bool
-verbAtLeast opts v = flag optVerbosity opts >= v
-
-dump :: Options -> Dump -> Bool
-dump opts d = moduleFlag ((d `elem`) . optDump) opts
-
---
--- * Convenience functions for setting options
---
-
-setOptimization :: Optimization -> Bool -> Options
-setOptimization o b = modifyModuleFlags (setOptimization' o b)
-
-setOptimization' :: Optimization -> Bool -> ModuleFlags -> ModuleFlags
-setOptimization' o b f = f { optOptimizations = g (optOptimizations f)}
- where g = if b then Set.insert o else Set.delete o
-
---
--- * General utilities
---
-
-readMaybe :: Read a => String -> Maybe a
-readMaybe s = case reads s of
- [(x,"")] -> Just x
- _ -> Nothing
-
-toEnumBounded :: (Bounded a, Enum a, Ord a) => Int -> Maybe a
-toEnumBounded i = let mi = minBound
- ma = maxBound `asTypeOf` mi
- in if i >= fromEnum mi && i <= fromEnum ma
- then Just (toEnum i `asTypeOf` mi)
- else Nothing
-
-
-instance Functor OptDescr where
- fmap f (Option cs ss d s) = Option cs ss (fmap f d) s
-
-instance Functor ArgDescr where
- fmap f (NoArg x) = NoArg (f x)
- fmap f (ReqArg g s) = ReqArg (f . g) s
- fmap f (OptArg g s) = OptArg (f . g) s