[Haskell-cafe] GetOpt

Brian Hulley brianh at metamilk.com
Thu Apr 27 15:38:16 EDT 2006


Bulat Ziganshin wrote:
> Hello Tomasz,
> [snip]
> ultimately, the main problem of all options-parsing stuff i ever seen,
> is requirement to repeat option definition many times. if i have, say,
> 40 options, then i need to maintain 3 to 5 program fragments that deal
> with each option. something like this:
>
> data Options = Options { r :: Bool,
>                         x :: Int
>                         ....
>                       }
>
> options = { "r", "description"
>            ....
>          }
>
> main = do list <- getOpts options cmdline
>          let options = Options { r = findBoolOption list "r",
>                                  x = findIntOption list "x",
>                                  ....
>                                }
>

If it is not necessary to specify a specific command letter for each option, 
then perhaps options could be composed by something like (following code 
untested):

class OptionClass a where
      setOption :: a -> String -> IO ()
      getOptionDescription :: a -> String -> String

data Option = forall a. OptionClass a => Option a
instance OptionClass Option where
      setOption (Option a) = setOption a
      getOptionDescription (Option a ) opt = getOptionDescription a opt

data ComposedOption = ComposedOption _ [Option]
instance OptionClass ComposedOption where
      setOption (ComposedOption _ os) (c:cs) = setOption (os !! (fromEnum 
c - fromEnum 'a')) cs
      getOptionDescription (ComposedOption description os) (c:cs)=
                  description ++ "." ++ getOptionDescription (os !! 
(fromEnum x - fromEnum 'a')) cs

Then each element in a module that needs an option makes its own instance of 
the existential eg

data ModOption1 = ModOption1
data ModOption2 = ModOption2

instance OptionClass ModOption1 where
     setOption ModOption1 s = case s of
                                                   [] -> do -- set default 
value
                                                   s -> do -- parse s and 
set accordingly

     getOptionDescription ModOption1 optvalue =
                -- description of this option, possibly clarified to the 
specific example of optvalue
                -- "would read from the file 'foo.txt'" if optvalue == " 
foo.txt"

moduleOptions = ComposedOption "My module" [ModOption1, ModOption2]

Then in main, do:

allOptions = ComposedOption "Name of program" [Module1.moduleOptions, 
Module2.moduleOptions, ...]

A disadvantage would be that the options would involve multiple letters in 
general eg -aaaab -aba etc when there is a lot of nesting, but an advantage 
is that it allows libraries requiring options and code using such libraries 
to be written in a modular way.

Best regards, Brian. 



More information about the Haskell-Cafe mailing list