[Hackage] #223: allow per-package configuration options in config file

Hackage trac at galois.com
Tue Mar 4 05:57:02 EST 2008


#223: allow per-package configuration options in config file
---------------------------------+------------------------------------------
  Reporter:  duncan              |        Owner:  mnislaih 
      Type:  enhancement         |       Status:  assigned 
  Priority:  normal              |    Milestone:  Cabal-1.4
 Component:  cabal-install tool  |      Version:  1.2.3.0  
  Severity:  normal              |   Resolution:           
  Keywords:                      |   Difficulty:  normal   
Ghcversion:  6.8.2               |     Platform:           
---------------------------------+------------------------------------------
Comment (by mnislaih):

 Since this is not a trivial refactoring and I am not a usual committer,
 here is a plan write-up.

 == Problem ==

          We have ConfigFlags, a data structure in typical database
 fashion,
          a dictionary of plain values composed of several fields.
          There are two main goals
           a) Be able to serialize it (done now via ParseUtils.FieldDescrs)

           b) Be able to manipulate it via command line flags (done via
 Command.Option)

          For a), we want a format that is human readable and modifiable.

          For b), we want to be able to specify the flags, with an
 expressivity
          comparable to the GetOpt language.

          Overall, we want to have a coherence and be able to reuse code.
          We may want to see these as two facets of the same problem
          and be able to specify them in one single place.

          (and in Haskell 98 of course)


 == Solution 1 ==

 Specify b) via Distribution.Command.Option, and then convert those options
 to
 ParseUtils.FieldDescrs automatically, which can be serialized for b).
 The problem is that NoArg/OptArg options cannot really be converted to
 FieldDescrs.
 We are missing a proper name for the field in the serialized file, and
 since
 there are usually several Options of this kind associated to one field, we
 want to see them as defining the possible values of the field. But we
 cannot collect them,
 as the option description is missing a declarative reference to which
 record they modify in the data structure.

 {{{
 option :: [Char] -> [String] -> String -> c -> d
        -> (c -> d -> ArgDescr a) -> Option a
 option ss ls d get set arg = Option ss ls d (arg get set)
 }}}

 There are getters and setters, but those are opaque functions.
 Hence, we can only automatically infer FieldDescrs for ReqArg options. The
 others must be inputed manually.

 This seems error prone and tricky to maintain to me, although it has the
 advantage of being the simplest refactoring among all the options.

 == Solution 2 ==
 If we reify the record, then options can be given a more declarative type.
 {{{
 option :: Record data field -> [Char] -> String -> String -> ArgDescr
 field -> Option field

 data Record data field =
   { get  :: data -> field
   , set  :: field -> data -> data
 }}}

 This is good enough to enable us to collect all the NoArg options related
 to
 one field, and condense a single FieldDescr out of it.

 == Solution 3 ==

 But why stop there? We can put more metadata in the Record descriptor.

 {{{
  interface :: OptInterface,
  desc      :: String,
  shape     :: Shape,
  ppr       :: field -> Doc
 }

 data OptInterface {
                       shortFlags :: [String],
                       longFlags  :: [String]  }

 data Shape field = StringValued (String -> ReadS field)
                  | Choice       (Map OptInterface field)
 }}}
 So now it is possible to extract an Option directly from this structure.
 {{{
 mkOption :: Record data field -> [Option data]
 }}}
 The definition of mkOption should be trivial. If the Record is
 StringValued
 then we get a single Option, otherwise we get an Option for every choice.

 And the same goes for FieldDescrs.
 {{{
 mkFieldDescr :: Record data field -> FieldDescr data
 }}}
 For the row name in the file we just take the first longFlag,
 and if it has a Choice shape then we build the trivial parser for it.
 Otherwise we just use the parser provided in StringValued.


 Finally, we could just extend FieldDescr to accomodate the role of Record
 above.
 But this poses the minor issue that FieldDescr 'instances' are provided in
 CabalInstall, whereas they would be required by Cabal already in
 Distribution.Setup.hs
 So they will need to be moved there.

-- 
Ticket URL: <http://hackage.haskell.org/trac/hackage/ticket/223#comment:2>
Hackage <http://haskell.org/cabal/>
Hackage: Cabal and related projects


More information about the cabal-devel mailing list