anchor.diff:  rec {
   
   
  -  mkOption = attrs: attrs // {_type = "option";};
  -
     hasType = x: isAttrs x && x ? _type;
     typeOf = x: if hasType x then x._type else "";
   
     isOption = attrs: (typeOf attrs) == "option";
  -
  +  mkOption = attrs: attrs // {
  +    _type = "option";
  +    # name (this is the name of the attributem it is automatically generated by the traversal)
  +    # default (value used when no definition exists)
  +    # example (documentation)
  +    # description (documentation)
  +    # type (option type, provide a default merge function and ensure type correctness)
  +    # merge (function used to merge definitions into one definition: [ /type/ ] -> /type/)
  +    # apply (convert the option value to ease the manipulation of the option result)
  +    # options (set of sub-options declarations & definitions)
  +  };
  +
  +  # Make the option declaration more user-friendly by adding default
  +  # settings and some verifications based on the declaration content (like
  +  # type correctness).
  +  addOptionMakeUp = {name, recurseInto}: decl:
  +    let
  +      init = {
  +        inherit name;
  +        merge = mergeDefaultOption;
  +        apply = lib.id;
  +      };
  +
  +      mergeFromType = opt:
  +        if decl ? type && decl.type ? merge then
  +          opt // { merge = decl.type.merge; }
  +        else
  +          opt;
  +
  +      addDeclaration = opt: opt // decl;
  +
  +      ensureMergeInputType = opt:
  +        if decl ? type then
  +          opt // {
  +            merge = list:
  +              if all decl.type.check list then
  +                opt.merge list
  +              else
  +                throw "One of the definitions has a bad type.";
  +          }
  +        else opt;
  +
  +      ensureDefaultType = opt:
  +        if decl ? type && decl ? default then
  +          opt // {
  +            default =
  +              if decl.type.check decl.default then
  +                decl.default
  +              else
  +                throw "The default value has a bad type.";
  +          }
  +        else opt;
  +
  +      handleOptionSets = opt:
  +        if decl ? type && decl.type.hasOptions then
  +          opt // {
  +            merge = list:
  +              decl.type.iter
  +                (path: opts: recurseInto path (decl.options ++ [opts]))
  +                opt.name
  +                (opt.merge list);
  +            options = recurseInto (decl.type.docPath opt.name) decl.options;
  +          }
  +        else
  +          opt;
  +    in
  +      foldl (opt: f: f opt) init [
  +        # default settings
  +        mergeFromType
  +
  +        # user settings
  +        addDeclaration
  +
  +        # override settings
  +        ensureMergeInputType
  +        ensureDefaultType
  +        handleOptionSets
  +      ];
  +
  +  # Merge a list of options containning different field.  This is useful to
  +  # separate the merge & apply fields from the interface.
  +  mergeOptionDecls = opts:
  +    if opts == [] then {}
  +    else if tail opts == [] then
  +      let opt = head opts; in
  +      if opt ? options then
  +        opt // { options = toList opt.options; }
  +      else
  +        opt
  +    else
  +      fold (opt1: opt2:
  +        lib.addErrorContext "opt1 = ${lib.showVal opt1}\nopt2 = ${lib.showVal opt2}" (
  +        # You cannot merge if two options have the same field.
  +        assert opt1 ? default -> ! opt2 ? default;
  +        assert opt1 ? example -> ! opt2 ? example;
  +        assert opt1 ? description -> ! opt2 ? description;
  +        assert opt1 ? merge -> ! opt2 ? merge;
  +        assert opt1 ? apply -> ! opt2 ? apply;
  +        assert opt1 ? type -> ! opt2 ? type;
  +        if opt1 ? options || opt2 ? options then
  +          opt1 // opt2 // {
  +            options =
  +               (toList (attrByPath ["options"] [] opt1))
  +            ++ (toList (attrByPath ["options"] [] opt2));
  +          }
  +        else
  +          opt1 // opt2
  +      )) {} opts;
  +
  +
  +  # name (name of the type)
  +  # check (boolean function)
  +  # merge (default merge function)
  +  # iter (iterate on all elements contained in this type)
  +  # fold (fold all elements contained in this type)
  +  # hasOptions (boolean: whatever this option contains an option set)
  +  # path (path contatenated to the option name contained contained in the option set)
  +  isOptionType = attrs: (typeOf attrs) == "option-type";
  +  mkOptionType = attrs@{
  +    name
  +  , check ? (x: true)
  +  , merge ? mergeDefaultOption
  +  # Handle complex structure types.
  +  , iter ? (f: path: v: f path v)
  +  , fold ? (op: nul: v: op v nul)
  +  , docPath ? lib.id
  +  # If the type can contains option sets.
  +  , hasOptions ? false
  +  }: { _type = "option-type";
  +    inherit name check merge iter fold docPath hasOptions;
  +  };
  +
  +
  +  type = {
  +
  +    infere = mkOptionType {
  +      name = "infered type";
  +    };
  +
  +    enable = mkOptionType {
  +      name = "boolean";
  +      check = builtins.isBool;
  +      merge = fold lib.or false;
  +    };
  +
  +    int = mkOptionType {
  +      name = "integer";
  +      check = builtins.isInt;
  +    };
  +
  +    string = mkOptionType {
  +      name = "string";
  +      check = x: builtins ? isString -> builtins.isString x;
  +      merge = lib.concatStrings;
  +    };
  +
  +    attrs = mkOptionType {
  +      name = "attribute set";
  +      check = builtins.isAttrs;
  +      merge = fold lib.mergeAttrs {};
  +    };
  +
  +    # derivation is a reserved keyword.
  +    package = mkOptionType {
  +      name = "derivation";
  +      check = x: builtins.isAttrs x && x ? outPath;
  +    };
  +
  +
  +    list = elemType: mkOptionType {
  +      name = "list of ${elemType.name}s";
  +      check = value: isList value && all elemType.check value;
  +      merge = concatLists;
  +      iter = f: path: list: map (elemType.iter f (path + ".*")) list;
  +      fold = op: nul: list: lib.fold (e: l: elemType.fold op l e) nul list;
  +      docPath = path: elemType (path + ".*");
  +      inherit (elemType) hasOptions;
  +    };
  +
  +    attrsOf = elemType: mkOptionType {
  +      name = "attribute set of ${elemType}s";
  +      check = x: builtins.isAttrs x
  +        && fold (e: v: v && elemType.check e) true (lib.attrValues x);
  +      merge = fold lib.mergeAttrs {};
  +      iter = f: path: set: lib.mapAttrs (name: elemType.iter f (path + "." + name)) set;
  +      fold = op: nul: set: fold (e: l: elemType.fold op l e) nul (lib.attrValues set);
  +      docPath = path: elemType (path + ".<name>");
  +      inherit (elemType) hasOptions;
  +    };
  +
  +    uniq = elemType: mkOptionType {
  +      inherit (elemType) name check iter fold docPath hasOptions;
  +      merge = list:
  +        if tail list == [] then
  +          head list
  +        else
  +          throw "Multiple definitions. Only one is allowed for this option.";
  +    };
  +
  +    nullOr = elemType: mkOptionType {
  +      inherit (elemType) name merge docPath hasOptions;
  +      check = x: builtins.isNull x || elemType.check x;
  +      iter = f: path: v: if v == null then v else elemType.iter f path v;
  +      fold = op: nul: v: if v == null then nul else elemType.fold op nul v;
  +    };
  +
  +    optionSet = mkOptionType {
  +      name = "option set";
  +      check = x: builtins.isAttrs x;
  +      hasOptions = true;
  +    };
  +
  +  };
  +
  +
  +  # !!! This function will be removed because this can be done with the
  +  # multiple option declarations.
     addDefaultOptionValues = defs: opts: opts //
       builtins.listToAttrs (map (defName:
         { name = defName;
  
positive.code:     if all isAttrs opts then
        lib.zip (attr: opts:
          let
            # Compute the path to reach the attribute.
            name = if path == "" then attr else path + "." + attr;
  
  
negative.code:           test = partition isOption opts;
            decls = test.right; defs = test.wrong;
  
            # Make the option declaration more user-friendly by adding default
            # settings and some verifications based on the declaration content
            # (like type correctness).
            opt = addOptionMakeUp
              { inherit name recurseInto; }
              (mergeOptionDecls decls);
  
            # Return the list of option sets.
            optAttrs = map delayProperties defs;
  