anchor.diff:      (x: if builtins ? isString then builtins.isString x else x + "")
       concatStrings;
   
  -  # Merge sets of options and bindings.
  -  # noOption: function to call if no option is declared.
  -  mergeOptionSets = noOption: path: opts:
  +
  +  # Handle the traversal of option sets.  All sets inside 'opts' are zipped
  +  # and options declaration and definition are separated.  If no option are
  +  # declared at a specific depth, then the function recurse into the values.
  +  # Other cases are handled by the optionHandler which contains two
  +  # functions that are used to defined your goal.
  +  # - export is a function which takes two arguments which are the option
  +  # and the list of values.
  +  # - notHandle is a function which takes the list of values are not handle
  +  # by this function.
  +  handleOptionSets = optionHandler@{export, notHandle, ...}: path: opts:
       if all __isAttrs opts then
         zip (attr: opts:
           let
             name = if path == "" then attr else path + "." + attr;
             test = partition isOption opts;
  -          opt = ({ merge = mergeDefaultOption; apply = id; } // head test.right);
  +          opt = {
  +            inherit name;
  +            merge = mergeDefaultOption;
  +            apply = id;
  +          } // (head test.right);
           in
  -          if test.right == [] then mergeOptionSets noOption name (map delayIf test.wrong)
  -          else if tail test.right != [] then throw "Multiple options for '${name}'."
  -          else if test.wrong == [] then opt.apply opt.default
  -          else opt.apply (opt.merge name (map evalIf test.wrong))
  +          if test.right == [] then handleOptionSets optionHandler name (map delayIf test.wrong)
  +          else addLocation "while evaluating the option ${name}:" (
  +            if tail test.right != [] then throw "Multiple options."
  +            else export opt (map evalIf test.wrong)
  +          )
         ) opts
  -   else noOption path opts;
  -
  -  # Keep all option declarations and add an attribute "name" inside
  -  # each option which contains the path that has to be followed to
  -  # access it.
  -  filterOptionSets = path: opts:
  -    if all __isAttrs opts then
  -      zip (attr: opts:
  -        let
  -          name = if path == "" then attr else path + "." + attr;
  -          test = partition isOption opts;
  -        in
  -          if test.right == [] then filterOptionSets name (map delayIf test.wrong)
  -          else if tail test.right != [] then  throw "Multiple options for '${name}'."
  -          else { inherit name; } // (head test.right)
  -      ) opts
  -    else {};
  +   else addLocation "while evaluating ${path}:" (notHandle opts);
  +
  +  # Merge option sets and produce a set of values which is the merging of
  +  # all options declare and defined.  If no values are defined for an
  +  # option, then the default value is used otherwise it use the merge
  +  # function of each option to get the result.
  +  mergeOptionSets = noOption: newMergeOptionSets; # ignore argument
  +  newMergeOptionSets =
  +    handleOptionSets {
  +      export = opt: values:
  +        opt.apply (
  +          if values == [] then
  +            if opt ? default then opt.default
  +            else throw "Not defined."
  +          else opt.merge (opt.name) values
  +        );
  +      notHandle = throw "Used without option declaration.";
  +    };
  +
  +  # Keep all option declarations.
  +  filterOptionSets =
  +    handleOptionSets {
  +      export = opt: values: opt;
  +      notHandle = {};
  +    };
   
     # Evaluate a list of option sets that would be merged with the
     # function "merge" which expects two arguments.  The attribute named
  
positive.code:       # call configuration "files" with one of the existing convention.
        optionSet = config: configFun:
          if __isFunction configFun then
            let result = configFun { inherit pkgs config; }; in
          # {pkgs, config, ...}: {..}
            if builtins.isAttrs result then result
          # pkgs: config: {..}
            else configFun pkgs config
          # {..}
          else configFun;
  
  
negative.code:     else if all __isAttrs list then mergeAttrs list
      else if all (x: true == x || false == x) list then fold logicalOR false list
      else if all (x: x == toString x) list then concatStrings list
      else throw "Cannot merge values.";
  
    mergeTypedOption = typeName: predicate: merge: name: list:
      if all predicate list then merge list
      else throw "Expect a ${typeName}.";
  
    mergeEnableOption = mergeTypedOption "boolean"
      (x: true == x || false == x) (fold logicalOR false);
  