about summary refs log tree commit diff
path: root/nixpkgs/lib/attrsets.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/lib/attrsets.nix')
-rw-r--r--nixpkgs/lib/attrsets.nix1866
1 files changed, 1329 insertions, 537 deletions
diff --git a/nixpkgs/lib/attrsets.nix b/nixpkgs/lib/attrsets.nix
index 34054460ba76..de5968b95348 100644
--- a/nixpkgs/lib/attrsets.nix
+++ b/nixpkgs/lib/attrsets.nix
@@ -1,4 +1,6 @@
-/* Operations on attribute sets. */
+/**
+  Operations on attribute sets.
+*/
 { lib }:
 
 let
@@ -12,35 +14,57 @@ rec {
   inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr removeAttrs;
 
 
-  /* Return an attribute from nested attribute sets.
+  /**
+    Return an attribute from nested attribute sets.
+
+    Nix has an [attribute selection operator `. or`](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
+
+    ```nix
+    (x.a.b or 6) == attrByPath ["a" "b"] 6 x
+    # and
+    (x.${f p}."example.com" or 6) == attrByPath [ (f p) "example.com" ] 6 x
+    ```
+
 
-     Nix has an [attribute selection operator `. or`](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
+    # Inputs
 
-     ```nix
-     (x.a.b or 6) == attrByPath ["a" "b"] 6 x
-     # and
-     (x.${f p}."example.com" or 6) == attrByPath [ (f p) "example.com" ] 6 x
-     ```
+    `attrPath`
 
-     Example:
-       x = { a = { b = 3; }; }
-       # ["a" "b"] is equivalent to x.a.b
-       # 6 is a default value to return if the path does not exist in attrset
-       attrByPath ["a" "b"] 6 x
-       => 3
-       attrByPath ["z" "z"] 6 x
-       => 6
+    : A list of strings representing the attribute path to return from `set`
 
-     Type:
-       attrByPath :: [String] -> Any -> AttrSet -> Any
+    `default`
+
+    : Default value if `attrPath` does not resolve to an existing value
+
+    `set`
+
+    : The nested attribute set to select values from
+
+    # Type
 
+    ```
+    attrByPath :: [String] -> Any -> AttrSet -> Any
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.attrByPath` usage example
+
+    ```nix
+    x = { a = { b = 3; }; }
+    # ["a" "b"] is equivalent to x.a.b
+    # 6 is a default value to return if the path does not exist in attrset
+    attrByPath ["a" "b"] 6 x
+    => 3
+    attrByPath ["z" "z"] 6 x
+    => 6
+    ```
+
+    :::
   */
   attrByPath =
-    # A list of strings representing the attribute path to return from `set`
     attrPath:
-    # Default value if `attrPath` does not resolve to an existing value
     default:
-    # The nested attribute set to select values from
     set:
     let
       lenAttrPath = length attrPath;
@@ -57,37 +81,57 @@ rec {
     in
       attrByPath' 0 set;
 
-  /* Return if an attribute from nested attribute set exists.
+  /**
+    Return if an attribute from nested attribute set exists.
+
+    Nix has a [has attribute operator `?`](https://nixos.org/manual/nix/stable/language/operators#has-attribute), which is sufficient for such queries, as long as the number of attributes is static. For example:
 
-     Nix has a [has attribute operator `?`](https://nixos.org/manual/nix/stable/language/operators#has-attribute), which is sufficient for such queries, as long as the number of attributes is static. For example:
+    ```nix
+    (x?a.b) == hasAttryByPath ["a" "b"] x
+    # and
+    (x?${f p}."example.com") == hasAttryByPath [ (f p) "example.com" ] x
+    ```
+
+    **Laws**:
+     1.  ```nix
+         hasAttrByPath [] x == true
+         ```
+
+
+    # Inputs
 
-     ```nix
-     (x?a.b) == hasAttryByPath ["a" "b"] x
-     # and
-     (x?${f p}."example.com") == hasAttryByPath [ (f p) "example.com" ] x
-     ```
+    `attrPath`
 
-     **Laws**:
-      1.  ```nix
-          hasAttrByPath [] x == true
-          ```
+    : A list of strings representing the attribute path to check from `set`
 
-     Example:
-       x = { a = { b = 3; }; }
-       hasAttrByPath ["a" "b"] x
-       => true
-       hasAttrByPath ["z" "z"] x
-       => false
-       hasAttrByPath [] (throw "no need")
-       => true
+    `e`
 
-    Type:
-      hasAttrByPath :: [String] -> AttrSet -> Bool
+    : The nested attribute set to check
+
+    # Type
+
+    ```
+    hasAttrByPath :: [String] -> AttrSet -> Bool
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.hasAttrByPath` usage example
+
+    ```nix
+    x = { a = { b = 3; }; }
+    hasAttrByPath ["a" "b"] x
+    => true
+    hasAttrByPath ["z" "z"] x
+    => false
+    hasAttrByPath [] (throw "no need")
+    => true
+    ```
+
+    :::
   */
   hasAttrByPath =
-    # A list of strings representing the attribute path to check from `set`
     attrPath:
-    # The nested attribute set to check
     e:
     let
       lenAttrPath = length attrPath;
@@ -103,7 +147,7 @@ rec {
     in
       hasAttrByPath' 0 e;
 
-  /*
+  /**
     Return the longest prefix of an attribute path that refers to an existing attribute in a nesting of attribute sets.
 
     Can be used after [`mapAttrsRecursiveCond`](#function-library-lib.attrsets.mapAttrsRecursiveCond) to apply a condition,
@@ -120,24 +164,43 @@ rec {
         hasAttrByPath (attrsets.longestValidPathPrefix p x) x == true
         ```
 
-    Example:
-      x = { a = { b = 3; }; }
-      attrsets.longestValidPathPrefix ["a" "b" "c"] x
-      => ["a" "b"]
-      attrsets.longestValidPathPrefix ["a"] x
-      => ["a"]
-      attrsets.longestValidPathPrefix ["z" "z"] x
-      => []
-      attrsets.longestValidPathPrefix ["z" "z"] (throw "no need")
-      => []
-
-    Type:
-      attrsets.longestValidPathPrefix :: [String] -> Value -> [String]
+
+    # Inputs
+
+    `attrPath`
+
+    : A list of strings representing the longest possible path that may be returned.
+
+    `v`
+
+    : The nested attribute set to check.
+
+    # Type
+
+    ```
+    attrsets.longestValidPathPrefix :: [String] -> Value -> [String]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.longestValidPathPrefix` usage example
+
+    ```nix
+    x = { a = { b = 3; }; }
+    attrsets.longestValidPathPrefix ["a" "b" "c"] x
+    => ["a" "b"]
+    attrsets.longestValidPathPrefix ["a"] x
+    => ["a"]
+    attrsets.longestValidPathPrefix ["z" "z"] x
+    => []
+    attrsets.longestValidPathPrefix ["z" "z"] (throw "no need")
+    => []
+    ```
+
+    :::
   */
   longestValidPathPrefix =
-    # A list of strings representing the longest possible path that may be returned.
     attrPath:
-    # The nested attribute set to check.
     v:
     let
       lenAttrPath = length attrPath;
@@ -168,19 +231,39 @@ rec {
     in
       getPrefixForSetAtIndex v 0;
 
-  /* Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
+  /**
+    Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
+
 
-     Example:
-       setAttrByPath ["a" "b"] 3
-       => { a = { b = 3; }; }
+    # Inputs
 
-     Type:
-       setAttrByPath :: [String] -> Any -> AttrSet
+    `attrPath`
+
+    : A list of strings representing the attribute path to set
+
+    `value`
+
+    : The value to set at the location described by `attrPath`
+
+    # Type
+
+    ```
+    setAttrByPath :: [String] -> Any -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.setAttrByPath` usage example
+
+    ```nix
+    setAttrByPath ["a" "b"] 3
+    => { a = { b = 3; }; }
+    ```
+
+    :::
   */
   setAttrByPath =
-    # A list of strings representing the attribute path to set
     attrPath:
-    # The value to set at the location described by `attrPath`
     value:
     let
       len = length attrPath;
@@ -190,47 +273,89 @@ rec {
         else { ${elemAt attrPath n} = atDepth (n + 1); };
     in atDepth 0;
 
-  /* Like `attrByPath`, but without a default value. If it doesn't find the
-     path it will throw an error.
+  /**
+    Like `attrByPath`, but without a default value. If it doesn't find the
+    path it will throw an error.
 
-     Nix has an [attribute selection operator](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
+    Nix has an [attribute selection operator](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
 
     ```nix
-     x.a.b == getAttrByPath ["a" "b"] x
-     # and
-     x.${f p}."example.com" == getAttrByPath [ (f p) "example.com" ] x
-     ```
-
-     Example:
-       x = { a = { b = 3; }; }
-       getAttrFromPath ["a" "b"] x
-       => 3
-       getAttrFromPath ["z" "z"] x
-       => error: cannot find attribute `z.z'
-
-     Type:
-       getAttrFromPath :: [String] -> AttrSet -> Any
+    x.a.b == getAttrByPath ["a" "b"] x
+    # and
+    x.${f p}."example.com" == getAttrByPath [ (f p) "example.com" ] x
+    ```
+
+
+    # Inputs
+
+    `attrPath`
+
+    : A list of strings representing the attribute path to get from `set`
+
+    `set`
+
+    : The nested attribute set to find the value in.
+
+    # Type
+
+    ```
+    getAttrFromPath :: [String] -> AttrSet -> Any
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getAttrFromPath` usage example
+
+    ```nix
+    x = { a = { b = 3; }; }
+    getAttrFromPath ["a" "b"] x
+    => 3
+    getAttrFromPath ["z" "z"] x
+    => error: cannot find attribute `z.z'
+    ```
+
+    :::
   */
   getAttrFromPath =
-    # A list of strings representing the attribute path to get from `set`
     attrPath:
-    # The nested attribute set to find the value in.
     set:
     attrByPath attrPath (abort ("cannot find attribute `" + concatStringsSep "." attrPath + "'")) set;
 
-  /* Map each attribute in the given set and merge them into a new attribute set.
+  /**
+    Map each attribute in the given set and merge them into a new attribute set.
+
+
+    # Inputs
 
-     Type:
-       concatMapAttrs :: (String -> a -> AttrSet) -> AttrSet -> AttrSet
+    `f`
 
-     Example:
-       concatMapAttrs
-         (name: value: {
-           ${name} = value;
-           ${name + value} = value;
-         })
-         { x = "a"; y = "b"; }
-       => { x = "a"; xa = "a"; y = "b"; yb = "b"; }
+    : 1\. Function argument
+
+    `v`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    concatMapAttrs :: (String -> a -> AttrSet) -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.concatMapAttrs` usage example
+
+    ```nix
+    concatMapAttrs
+      (name: value: {
+        ${name} = value;
+        ${name + value} = value;
+      })
+      { x = "a"; y = "b"; }
+    => { x = "a"; xa = "a"; y = "b"; yb = "b"; }
+    ```
+
+    :::
   */
   concatMapAttrs = f: v:
     foldl' mergeAttrs { }
@@ -239,49 +364,61 @@ rec {
       );
 
 
-  /* Update or set specific paths of an attribute set.
-
-     Takes a list of updates to apply and an attribute set to apply them to,
-     and returns the attribute set with the updates applied. Updates are
-     represented as `{ path = ...; update = ...; }` values, where `path` is a
-     list of strings representing the attribute path that should be updated,
-     and `update` is a function that takes the old value at that attribute path
-     as an argument and returns the new
-     value it should be.
-
-     Properties:
-
-     - Updates to deeper attribute paths are applied before updates to more
-       shallow attribute paths
-
-     - Multiple updates to the same attribute path are applied in the order
-       they appear in the update list
-
-     - If any but the last `path` element leads into a value that is not an
-       attribute set, an error is thrown
-
-     - If there is an update for an attribute path that doesn't exist,
-       accessing the argument in the update function causes an error, but
-       intermediate attribute sets are implicitly created as needed
-
-     Example:
-       updateManyAttrsByPath [
-         {
-           path = [ "a" "b" ];
-           update = old: { d = old.c; };
-         }
-         {
-           path = [ "a" "b" "c" ];
-           update = old: old + 1;
-         }
-         {
-           path = [ "x" "y" ];
-           update = old: "xy";
-         }
-       ] { a.b.c = 0; }
-       => { a = { b = { d = 1; }; }; x = { y = "xy"; }; }
-
-    Type: updateManyAttrsByPath :: [{ path :: [String]; update :: (Any -> Any); }] -> AttrSet -> AttrSet
+  /**
+    Update or set specific paths of an attribute set.
+
+    Takes a list of updates to apply and an attribute set to apply them to,
+    and returns the attribute set with the updates applied. Updates are
+    represented as `{ path = ...; update = ...; }` values, where `path` is a
+    list of strings representing the attribute path that should be updated,
+    and `update` is a function that takes the old value at that attribute path
+    as an argument and returns the new
+    value it should be.
+
+    Properties:
+
+    - Updates to deeper attribute paths are applied before updates to more
+      shallow attribute paths
+
+    - Multiple updates to the same attribute path are applied in the order
+      they appear in the update list
+
+    - If any but the last `path` element leads into a value that is not an
+      attribute set, an error is thrown
+
+    - If there is an update for an attribute path that doesn't exist,
+      accessing the argument in the update function causes an error, but
+      intermediate attribute sets are implicitly created as needed
+
+    # Type
+
+    ```
+    updateManyAttrsByPath :: [{ path :: [String]; update :: (Any -> Any); }] -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.updateManyAttrsByPath` usage example
+
+    ```nix
+    updateManyAttrsByPath [
+      {
+        path = [ "a" "b" ];
+        update = old: { d = old.c; };
+      }
+      {
+        path = [ "a" "b" "c" ];
+        update = old: old + 1;
+      }
+      {
+        path = [ "x" "y" ];
+        update = old: "xy";
+      }
+    ] { a.b.c = 0; }
+    => { a = { b = { d = 1; }; }; x = { y = "xy"; }; }
+    ```
+
+    :::
   */
   updateManyAttrsByPath = let
     # When recursing into attributes, instead of updating the `path` of each
@@ -342,96 +479,208 @@ rec {
 
   in updates: value: go 0 true value updates;
 
-  /* Return the specified attributes from a set.
+  /**
+    Return the specified attributes from a set.
+
+
+    # Inputs
+
+    `nameList`
+
+    : The list of attributes to fetch from `set`. Each attribute name must exist on the attrbitue set
 
-     Example:
-       attrVals ["a" "b" "c"] as
-       => [as.a as.b as.c]
+    `set`
 
-     Type:
-       attrVals :: [String] -> AttrSet -> [Any]
+    : The set to get attribute values from
+
+    # Type
+
+    ```
+    attrVals :: [String] -> AttrSet -> [Any]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.attrVals` usage example
+
+    ```nix
+    attrVals ["a" "b" "c"] as
+    => [as.a as.b as.c]
+    ```
+
+    :::
   */
   attrVals =
-    # The list of attributes to fetch from `set`. Each attribute name must exist on the attrbitue set
     nameList:
-    # The set to get attribute values from
     set: map (x: set.${x}) nameList;
 
 
-  /* Return the values of all attributes in the given set, sorted by
-     attribute name.
+  /**
+    Return the values of all attributes in the given set, sorted by
+    attribute name.
 
-     Example:
-       attrValues {c = 3; a = 1; b = 2;}
-       => [1 2 3]
+    # Type
 
-     Type:
-       attrValues :: AttrSet -> [Any]
+    ```
+    attrValues :: AttrSet -> [Any]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.attrValues` usage example
+
+    ```nix
+    attrValues {c = 3; a = 1; b = 2;}
+    => [1 2 3]
+    ```
+
+    :::
   */
   attrValues = builtins.attrValues;
 
 
-  /* Given a set of attribute names, return the set of the corresponding
-     attributes from the given set.
+  /**
+    Given a set of attribute names, return the set of the corresponding
+    attributes from the given set.
+
+
+    # Inputs
+
+    `names`
 
-     Example:
-       getAttrs [ "a" "b" ] { a = 1; b = 2; c = 3; }
-       => { a = 1; b = 2; }
+    : A list of attribute names to get out of `set`
 
-     Type:
-       getAttrs :: [String] -> AttrSet -> AttrSet
+    `attrs`
+
+    : The set to get the named attributes from
+
+    # Type
+
+    ```
+    getAttrs :: [String] -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getAttrs` usage example
+
+    ```nix
+    getAttrs [ "a" "b" ] { a = 1; b = 2; c = 3; }
+    => { a = 1; b = 2; }
+    ```
+
+    :::
   */
   getAttrs =
-    # A list of attribute names to get out of `set`
     names:
-    # The set to get the named attributes from
     attrs: genAttrs names (name: attrs.${name});
 
-  /* Collect each attribute named `attr` from a list of attribute
-     sets.  Sets that don't contain the named attribute are ignored.
+  /**
+    Collect each attribute named `attr` from a list of attribute
+    sets.  Sets that don't contain the named attribute are ignored.
+
+    # Inputs
+
+    `attr`
+
+    : The attribute name to get out of the sets.
 
-     Example:
-       catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
-       => [1 2]
+    `list`
 
-     Type:
-       catAttrs :: String -> [AttrSet] -> [Any]
+    : The list of attribute sets to go through
+
+    # Type
+
+    ```
+    catAttrs :: String -> [AttrSet] -> [Any]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.catAttrs` usage example
+
+    ```nix
+    catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
+    => [1 2]
+    ```
+
+    :::
   */
   catAttrs = builtins.catAttrs;
 
 
-  /* Filter an attribute set by removing all attributes for which the
-     given predicate return false.
+  /**
+    Filter an attribute set by removing all attributes for which the
+    given predicate return false.
+
+
+    # Inputs
+
+    `pred`
 
-     Example:
-       filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; }
-       => { foo = 1; }
+    : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
 
-     Type:
-       filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet
+    `set`
+
+    : The attribute set to filter
+
+    # Type
+
+    ```
+    filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.filterAttrs` usage example
+
+    ```nix
+    filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; }
+    => { foo = 1; }
+    ```
+
+    :::
   */
   filterAttrs =
-    # Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
     pred:
-    # The attribute set to filter
     set:
     listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set));
 
 
-  /* Filter an attribute set recursively by removing all attributes for
-     which the given predicate return false.
+  /**
+    Filter an attribute set recursively by removing all attributes for
+    which the given predicate return false.
+
+
+    # Inputs
+
+    `pred`
+
+    : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
+
+    `set`
+
+    : The attribute set to filter
+
+    # Type
+
+    ```
+    filterAttrsRecursive :: (String -> Any -> Bool) -> AttrSet -> AttrSet
+    ```
 
-     Example:
-       filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; }
-       => { foo = {}; }
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.filterAttrsRecursive` usage example
 
-     Type:
-       filterAttrsRecursive :: (String -> Any -> Bool) -> AttrSet -> AttrSet
+    ```nix
+    filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; }
+    => { foo = {}; }
+    ```
+
+    :::
   */
   filterAttrsRecursive =
-    # Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
     pred:
-    # The attribute set to filter
     set:
     listToAttrs (
       concatMap (name:
@@ -445,59 +694,84 @@ rec {
       ) (attrNames set)
     );
 
-   /*
+   /**
     Like [`lib.lists.foldl'`](#function-library-lib.lists.foldl-prime) but for attribute sets.
     Iterates over every name-value pair in the given attribute set.
     The result of the callback function is often called `acc` for accumulator. It is passed between callbacks from left to right and the final `acc` is the return value of `foldlAttrs`.
 
     Attention:
-      There is a completely different function
-      `lib.foldAttrs`
-      which has nothing to do with this function, despite the similar name.
-
-    Example:
-      foldlAttrs
-        (acc: name: value: {
-          sum = acc.sum + value;
-          names = acc.names ++ [name];
-        })
-        { sum = 0; names = []; }
-        {
-          foo = 1;
-          bar = 10;
-        }
-      ->
-        {
-          sum = 11;
-          names = ["bar" "foo"];
-        }
-
-      foldlAttrs
-        (throw "function not needed")
-        123
-        {};
-      ->
-        123
-
-      foldlAttrs
-        (acc: _: _: acc)
-        3
-        { z = throw "value not needed"; a = throw "value not needed"; };
-      ->
-        3
-
-      The accumulator doesn't have to be an attrset.
-      It can be as simple as a number or string.
-
-      foldlAttrs
-        (acc: _: v: acc * 10 + v)
-        1
-        { z = 1; a = 2; };
-      ->
-        121
-
-    Type:
-      foldlAttrs :: ( a -> String -> b -> a ) -> a -> { ... :: b } -> a
+
+    There is a completely different function `lib.foldAttrs`
+    which has nothing to do with this function, despite the similar name.
+
+
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
+
+    `init`
+
+    : 2\. Function argument
+
+    `set`
+
+    : 3\. Function argument
+
+    # Type
+
+    ```
+    foldlAttrs :: ( a -> String -> b -> a ) -> a -> { ... :: b } -> a
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.foldlAttrs` usage example
+
+    ```nix
+    foldlAttrs
+      (acc: name: value: {
+        sum = acc.sum + value;
+        names = acc.names ++ [name];
+      })
+      { sum = 0; names = []; }
+      {
+        foo = 1;
+        bar = 10;
+      }
+    ->
+      {
+        sum = 11;
+        names = ["bar" "foo"];
+      }
+
+    foldlAttrs
+      (throw "function not needed")
+      123
+      {};
+    ->
+      123
+
+    foldlAttrs
+      (acc: _: _: acc)
+      3
+      { z = throw "value not needed"; a = throw "value not needed"; };
+    ->
+      3
+
+    The accumulator doesn't have to be an attrset.
+    It can be as simple as a number or string.
+
+    foldlAttrs
+      (acc: _: v: acc * 10 + v)
+      1
+      { z = 1; a = 2; };
+    ->
+      121
+    ```
+
+    :::
   */
   foldlAttrs = f: init: set:
     foldl'
@@ -505,22 +779,44 @@ rec {
       init
       (attrNames set);
 
-  /* Apply fold functions to values grouped by key.
+  /**
+    Apply fold functions to values grouped by key.
+
+
+    # Inputs
+
+    `op`
+
+    : A function, given a value and a collector combines the two.
+
+    `nul`
+
+    : The starting value.
+
+    `list_of_attrs`
+
+    : A list of attribute sets to fold together by key.
+
+    # Type
+
+    ```
+    foldAttrs :: (Any -> Any -> Any) -> Any -> [AttrSets] -> Any
+    ```
 
-     Example:
-       foldAttrs (item: acc: [item] ++ acc) [] [{ a = 2; } { a = 3; }]
-       => { a = [ 2 3 ]; }
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.foldAttrs` usage example
 
-     Type:
-       foldAttrs :: (Any -> Any -> Any) -> Any -> [AttrSets] -> Any
+    ```nix
+    foldAttrs (item: acc: [item] ++ acc) [] [{ a = 2; } { a = 3; }]
+    => { a = [ 2 3 ]; }
+    ```
 
+    :::
   */
   foldAttrs =
-    # A function, given a value and a collector combines the two.
     op:
-    # The starting value.
     nul:
-    # A list of attribute sets to fold together by key.
     list_of_attrs:
     foldr (n: a:
         foldr (name: o:
@@ -529,26 +825,46 @@ rec {
     ) {} list_of_attrs;
 
 
-  /* Recursively collect sets that verify a given predicate named `pred`
-     from the set `attrs`.  The recursion is stopped when the predicate is
-     verified.
+  /**
+    Recursively collect sets that verify a given predicate named `pred`
+    from the set `attrs`. The recursion is stopped when the predicate is
+    verified.
+
 
-     Example:
-       collect isList { a = { b = ["b"]; }; c = [1]; }
-       => [["b"] [1]]
+    # Inputs
 
-       collect (x: x ? outPath)
-          { a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
-       => [{ outPath = "a/"; } { outPath = "b/"; }]
+    `pred`
+
+    : Given an attribute's value, determine if recursion should stop.
+
+    `attrs`
+
+    : The attribute set to recursively collect.
+
+    # Type
 
-     Type:
-       collect :: (AttrSet -> Bool) -> AttrSet -> [x]
+    ```
+    collect :: (AttrSet -> Bool) -> AttrSet -> [x]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.collect` usage example
+
+    ```nix
+    collect isList { a = { b = ["b"]; }; c = [1]; }
+    => [["b"] [1]]
+
+    collect (x: x ? outPath)
+       { a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
+    => [{ outPath = "a/"; } { outPath = "b/"; }]
+    ```
+
+    :::
   */
   collect =
-  # Given an attribute's value, determine if recursion should stop.
-  pred:
-  # The attribute set to recursively collect.
-  attrs:
+    pred:
+    attrs:
     if pred attrs then
       [ attrs ]
     else if isAttrs attrs then
@@ -556,21 +872,39 @@ rec {
     else
       [];
 
-  /* Return the cartesian product of attribute set value combinations.
-
-    Example:
-      cartesianProductOfSets { a = [ 1 2 ]; b = [ 10 20 ]; }
-      => [
-           { a = 1; b = 10; }
-           { a = 1; b = 20; }
-           { a = 2; b = 10; }
-           { a = 2; b = 20; }
-         ]
-     Type:
-       cartesianProductOfSets :: AttrSet -> [AttrSet]
+  /**
+    Return the cartesian product of attribute set value combinations.
+
+
+    # Inputs
+
+    `attrsOfLists`
+
+    : Attribute set with attributes that are lists of values
+
+    # Type
+
+    ```
+    cartesianProductOfSets :: AttrSet -> [AttrSet]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.cartesianProductOfSets` usage example
+
+    ```nix
+    cartesianProductOfSets { a = [ 1 2 ]; b = [ 10 20 ]; }
+    => [
+         { a = 1; b = 10; }
+         { a = 1; b = 20; }
+         { a = 2; b = 10; }
+         { a = 2; b = 20; }
+       ]
+    ```
+
+    :::
   */
   cartesianProductOfSets =
-    # Attribute set with attributes that are lists of values
     attrsOfLists:
     foldl' (listOfAttrs: attrName:
       concatMap (attrs:
@@ -579,76 +913,155 @@ rec {
     ) [{}] (attrNames attrsOfLists);
 
 
-  /* Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`.
+  /**
+    Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`.
+
+
+    # Inputs
 
-     Example:
-       nameValuePair "some" 6
-       => { name = "some"; value = 6; }
+    `name`
 
-     Type:
-       nameValuePair :: String -> Any -> { name :: String; value :: Any; }
+    : Attribute name
+
+    `value`
+
+    : Attribute value
+
+    # Type
+
+    ```
+    nameValuePair :: String -> Any -> { name :: String; value :: Any; }
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.nameValuePair` usage example
+
+    ```nix
+    nameValuePair "some" 6
+    => { name = "some"; value = 6; }
+    ```
+
+    :::
   */
   nameValuePair =
-    # Attribute name
     name:
-    # Attribute value
     value:
     { inherit name value; };
 
 
-  /* Apply a function to each element in an attribute set, creating a new attribute set.
+  /**
+    Apply a function to each element in an attribute set, creating a new attribute set.
+
+    # Inputs
+
+    `f`
 
-     Example:
-       mapAttrs (name: value: name + "-" + value)
-          { x = "foo"; y = "bar"; }
-       => { x = "x-foo"; y = "y-bar"; }
+    : A function that takes an attribute name and its value, and returns the new value for the attribute.
 
-     Type:
-       mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet
+    `attrset`
+
+    : The attribute set to iterate through.
+
+    # Type
+
+    ```
+    mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mapAttrs` usage example
+
+    ```nix
+    mapAttrs (name: value: name + "-" + value)
+       { x = "foo"; y = "bar"; }
+    => { x = "x-foo"; y = "y-bar"; }
+    ```
+
+    :::
   */
   mapAttrs = builtins.mapAttrs;
 
 
-  /* Like `mapAttrs`, but allows the name of each attribute to be
-     changed in addition to the value.  The applied function should
-     return both the new name and value as a `nameValuePair`.
+  /**
+    Like `mapAttrs`, but allows the name of each attribute to be
+    changed in addition to the value.  The applied function should
+    return both the new name and value as a `nameValuePair`.
+
+
+    # Inputs
 
-     Example:
-       mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
-          { x = "a"; y = "b"; }
-       => { foo_x = "bar-a"; foo_y = "bar-b"; }
+    `f`
 
-     Type:
-       mapAttrs' :: (String -> Any -> { name :: String; value :: Any; }) -> AttrSet -> AttrSet
+    : A function, given an attribute's name and value, returns a new `nameValuePair`.
+
+    `set`
+
+    : Attribute set to map over.
+
+    # Type
+
+    ```
+    mapAttrs' :: (String -> Any -> { name :: String; value :: Any; }) -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mapAttrs'` usage example
+
+    ```nix
+    mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
+       { x = "a"; y = "b"; }
+    => { foo_x = "bar-a"; foo_y = "bar-b"; }
+    ```
+
+    :::
   */
   mapAttrs' =
-    # A function, given an attribute's name and value, returns a new `nameValuePair`.
     f:
-    # Attribute set to map over.
     set:
     listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
 
 
-  /* Call a function for each attribute in the given set and return
-     the result in a list.
+  /**
+    Call a function for each attribute in the given set and return
+    the result in a list.
+
+    # Inputs
+
+    `f`
 
-     Example:
-       mapAttrsToList (name: value: name + value)
-          { x = "a"; y = "b"; }
-       => [ "xa" "yb" ]
+    : A function, given an attribute's name and value, returns a new value.
 
-     Type:
-       mapAttrsToList :: (String -> a -> b) -> AttrSet -> [b]
+    `attrs`
 
+    : Attribute set to map over.
+
+    # Type
+
+    ```
+    mapAttrsToList :: (String -> a -> b) -> AttrSet -> [b]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mapAttrsToList` usage example
+
+    ```nix
+    mapAttrsToList (name: value: name + value)
+       { x = "a"; y = "b"; }
+    => [ "xa" "yb" ]
+    ```
+
+    :::
   */
   mapAttrsToList =
-    # A function, given an attribute's name and value, returns a new value.
     f:
-    # Attribute set to map over.
     attrs:
     map (name: f name attrs.${name}) (attrNames attrs);
 
-  /*
+  /**
     Deconstruct an attrset to a list of name-value pairs as expected by [`builtins.listToAttrs`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-listToAttrs).
     Each element of the resulting list is an attribute set with these attributes:
     - `name` (string): The name of the attribute
@@ -668,13 +1081,28 @@ rec {
     This is because the `listToAttrs` removes duplicate names and doesn't preserve the order of the list.
     :::
 
-    Example:
-      attrsToList { foo = 1; bar = "asdf"; }
-      => [ { name = "bar"; value = "asdf"; } { name = "foo"; value = 1; } ]
+    # Inputs
+
+    `set`
 
-    Type:
-      attrsToList :: AttrSet -> [ { name :: String; value :: Any; } ]
+    : The attribute set to deconstruct.
+
+    # Type
 
+    ```
+    attrsToList :: AttrSet -> [ { name :: String; value :: Any; } ]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.attrsToList` usage example
+
+    ```nix
+    attrsToList { foo = 1; bar = "asdf"; }
+    => [ { name = "bar"; value = "asdf"; } { name = "foo"; value = 1; } ]
+    ```
+
+    :::
   */
   attrsToList = mapAttrsToList nameValuePair;
 
@@ -705,9 +1133,7 @@ rec {
     ```
   */
   mapAttrsRecursive =
-    # A function that, given an attribute path as a list of strings and the corresponding attribute value, returns a new value.
     f:
-    # Attribute set to recursively map over.
     set:
     mapAttrsRecursiveCond (as: true) f set;
 
@@ -736,12 +1162,8 @@ rec {
     ```
   */
   mapAttrsRecursiveCond =
-    # A function that, given the attribute set the recursion is currently at, determines if to recurse deeper into that attribute set.
     cond:
-    # A function that, given an attribute path as a list of strings and the corresponding attribute value, returns a new value.
-    # The attribute value is either an attribute set for which `cond` returns false, or something other than an attribute set.
     f:
-    # Attribute set to recursively map over.
     set:
     let
       recurse = path:
@@ -754,48 +1176,95 @@ rec {
     recurse [ ] set;
 
 
-  /* Generate an attribute set by mapping a function over a list of
-     attribute names.
+  /**
+    Generate an attribute set by mapping a function over a list of
+    attribute names.
+
+
+    # Inputs
+
+    `names`
+
+    : Names of values in the resulting attribute set.
+
+    `f`
+
+    : A function, given the name of the attribute, returns the attribute's value.
+
+    # Type
+
+    ```
+    genAttrs :: [ String ] -> (String -> Any) -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.genAttrs` usage example
 
-     Example:
-       genAttrs [ "foo" "bar" ] (name: "x_" + name)
-       => { foo = "x_foo"; bar = "x_bar"; }
+    ```nix
+    genAttrs [ "foo" "bar" ] (name: "x_" + name)
+    => { foo = "x_foo"; bar = "x_bar"; }
+    ```
 
-     Type:
-       genAttrs :: [ String ] -> (String -> Any) -> AttrSet
+    :::
   */
   genAttrs =
-    # Names of values in the resulting attribute set.
     names:
-    # A function, given the name of the attribute, returns the attribute's value.
     f:
     listToAttrs (map (n: nameValuePair n (f n)) names);
 
 
-  /* Check whether the argument is a derivation. Any set with
-     `{ type = "derivation"; }` counts as a derivation.
+  /**
+    Check whether the argument is a derivation. Any set with
+    `{ type = "derivation"; }` counts as a derivation.
+
 
-     Example:
-       nixpkgs = import <nixpkgs> {}
-       isDerivation nixpkgs.ruby
-       => true
-       isDerivation "foobar"
-       => false
+    # Inputs
 
-     Type:
-       isDerivation :: Any -> Bool
+    `value`
+
+    : Value to check.
+
+    # Type
+
+    ```
+    isDerivation :: Any -> Bool
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.isDerivation` usage example
+
+    ```nix
+    nixpkgs = import <nixpkgs> {}
+    isDerivation nixpkgs.ruby
+    => true
+    isDerivation "foobar"
+    => false
+    ```
+
+    :::
   */
   isDerivation =
-    # Value to check.
     value: value.type or null == "derivation";
 
-   /* Converts a store path to a fake derivation.
+   /**
+    Converts a store path to a fake derivation.
+
+
+    # Inputs
+
+    `path`
 
-      Type:
-        toDerivation :: Path -> Derivation
-   */
+    : A store path to convert to a derivation.
+
+    # Type
+
+    ```
+    toDerivation :: Path -> Derivation
+    ```
+  */
    toDerivation =
-     # A store path to convert to a derivation.
      path:
      let
        path' = builtins.storePath path;
@@ -810,42 +1279,85 @@ rec {
     in res;
 
 
-  /* If `cond` is true, return the attribute set `as`,
-     otherwise an empty attribute set.
+  /**
+    If `cond` is true, return the attribute set `as`,
+    otherwise an empty attribute set.
+
+
+    # Inputs
+
+    `cond`
 
-     Example:
-       optionalAttrs (true) { my = "set"; }
-       => { my = "set"; }
-       optionalAttrs (false) { my = "set"; }
-       => { }
+    : Condition under which the `as` attribute set is returned.
+
+    `as`
+
+    : The attribute set to return if `cond` is `true`.
+
+    # Type
+
+    ```
+    optionalAttrs :: Bool -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.optionalAttrs` usage example
+
+    ```nix
+    optionalAttrs (true) { my = "set"; }
+    => { my = "set"; }
+    optionalAttrs (false) { my = "set"; }
+    => { }
+    ```
 
-     Type:
-       optionalAttrs :: Bool -> AttrSet -> AttrSet
+    :::
   */
   optionalAttrs =
-    # Condition under which the `as` attribute set is returned.
     cond:
-    # The attribute set to return if `cond` is `true`.
     as:
     if cond then as else {};
 
 
-  /* Merge sets of attributes and use the function `f` to merge attributes
-     values.
+  /**
+    Merge sets of attributes and use the function `f` to merge attributes
+    values.
+
+
+    # Inputs
+
+    `names`
 
-     Example:
-       zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}]
-       => { a = ["x" "y"]; }
+    : List of attribute names to zip.
 
-     Type:
-       zipAttrsWithNames :: [ String ] -> (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
+    `f`
+
+    : A function, accepts an attribute name, all the values, and returns a combined value.
+
+    `sets`
+
+    : List of values from the list of attribute sets.
+
+    # Type
+
+    ```
+    zipAttrsWithNames :: [ String ] -> (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.zipAttrsWithNames` usage example
+
+    ```nix
+    zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}]
+    => { a = ["x" "y"]; }
+    ```
+
+    :::
   */
   zipAttrsWithNames =
-    # List of attribute names to zip.
     names:
-    # A function, accepts an attribute name, all the values, and returns a combined value.
     f:
-    # List of values from the list of attribute sets.
     sets:
     listToAttrs (map (name: {
       inherit name;
@@ -853,52 +1365,91 @@ rec {
     }) names);
 
 
-  /* Merge sets of attributes and use the function f to merge attribute values.
-     Like `lib.attrsets.zipAttrsWithNames` with all key names are passed for `names`.
+  /**
+    Merge sets of attributes and use the function f to merge attribute values.
+    Like `lib.attrsets.zipAttrsWithNames` with all key names are passed for `names`.
 
-     Implementation note: Common names appear multiple times in the list of
-     names, hopefully this does not affect the system because the maximal
-     laziness avoid computing twice the same expression and `listToAttrs` does
-     not care about duplicated attribute names.
+    Implementation note: Common names appear multiple times in the list of
+    names, hopefully this does not affect the system because the maximal
+    laziness avoid computing twice the same expression and `listToAttrs` does
+    not care about duplicated attribute names.
 
-     Example:
-       zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}]
-       => { a = ["x" "y"]; b = ["z"]; }
+    # Type
+
+    ```
+    zipAttrsWith :: (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.zipAttrsWith` usage example
 
-     Type:
-       zipAttrsWith :: (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
+    ```nix
+    zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}]
+    => { a = ["x" "y"]; b = ["z"]; }
+    ```
+
+    :::
   */
   zipAttrsWith =
     builtins.zipAttrsWith or (f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets);
 
 
-  /* Merge sets of attributes and combine each attribute value in to a list.
+  /**
+    Merge sets of attributes and combine each attribute value in to a list.
+
+    Like `lib.attrsets.zipAttrsWith` with `(name: values: values)` as the function.
+
+    # Type
+
+    ```
+    zipAttrs :: [ AttrSet ] -> AttrSet
+    ```
 
-     Like `lib.attrsets.zipAttrsWith` with `(name: values: values)` as the function.
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.zipAttrs` usage example
 
-     Example:
-       zipAttrs [{a = "x";} {a = "y"; b = "z";}]
-       => { a = ["x" "y"]; b = ["z"]; }
+    ```nix
+    zipAttrs [{a = "x";} {a = "y"; b = "z";}]
+    => { a = ["x" "y"]; b = ["z"]; }
+    ```
 
-     Type:
-       zipAttrs :: [ AttrSet ] -> AttrSet
+    :::
   */
   zipAttrs = zipAttrsWith (name: values: values);
 
-  /*
+  /**
     Merge a list of attribute sets together using the `//` operator.
     In case of duplicate attributes, values from later list elements take precedence over earlier ones.
     The result is the same as `foldl mergeAttrs { }`, but the performance is better for large inputs.
     For n list elements, each with an attribute set containing m unique attributes, the complexity of this operation is O(nm log n).
 
-    Type:
-      mergeAttrsList :: [ Attrs ] -> Attrs
 
-    Example:
-      mergeAttrsList [ { a = 0; b = 1; } { c = 2; d = 3; } ]
-      => { a = 0; b = 1; c = 2; d = 3; }
-      mergeAttrsList [ { a = 0; } { a = 1; } ]
-      => { a = 1; }
+    # Inputs
+
+    `list`
+
+    : 1\. Function argument
+
+    # Type
+
+    ```
+    mergeAttrsList :: [ Attrs ] -> Attrs
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mergeAttrsList` usage example
+
+    ```nix
+    mergeAttrsList [ { a = 0; b = 1; } { c = 2; d = 3; } ]
+    => { a = 0; b = 1; c = 2; d = 3; }
+    mergeAttrsList [ { a = 0; } { a = 1; } ]
+    => { a = 1; }
+    ```
+
+    :::
   */
   mergeAttrsList = list:
     let
@@ -922,42 +1473,65 @@ rec {
       binaryMerge 0 (length list);
 
 
-  /* Does the same as the update operator '//' except that attributes are
-     merged until the given predicate is verified.  The predicate should
-     accept 3 arguments which are the path to reach the attribute, a part of
-     the first attribute set and a part of the second attribute set.  When
-     the predicate is satisfied, the value of the first attribute set is
-     replaced by the value of the second attribute set.
-
-     Example:
-       recursiveUpdateUntil (path: l: r: path == ["foo"]) {
-         # first attribute set
-         foo.bar = 1;
-         foo.baz = 2;
-         bar = 3;
-       } {
-         #second attribute set
-         foo.bar = 1;
-         foo.quz = 2;
-         baz = 4;
-       }
-
-       => {
-         foo.bar = 1; # 'foo.*' from the second set
-         foo.quz = 2; #
-         bar = 3;     # 'bar' from the first set
-         baz = 4;     # 'baz' from the second set
-       }
-
-     Type:
-       recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
+  /**
+    Does the same as the update operator '//' except that attributes are
+    merged until the given predicate is verified.  The predicate should
+    accept 3 arguments which are the path to reach the attribute, a part of
+    the first attribute set and a part of the second attribute set.  When
+    the predicate is satisfied, the value of the first attribute set is
+    replaced by the value of the second attribute set.
+
+
+    # Inputs
+
+    `pred`
+
+    : Predicate, taking the path to the current attribute as a list of strings for attribute names, and the two values at that path from the original arguments.
+
+    `lhs`
+
+    : Left attribute set of the merge.
+
+    `rhs`
+
+    : Right attribute set of the merge.
+
+    # Type
+
+    ```
+    recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.recursiveUpdateUntil` usage example
+
+    ```nix
+    recursiveUpdateUntil (path: l: r: path == ["foo"]) {
+      # first attribute set
+      foo.bar = 1;
+      foo.baz = 2;
+      bar = 3;
+    } {
+      #second attribute set
+      foo.bar = 1;
+      foo.quz = 2;
+      baz = 4;
+    }
+
+    => {
+      foo.bar = 1; # 'foo.*' from the second set
+      foo.quz = 2; #
+      bar = 3;     # 'bar' from the first set
+      baz = 4;     # 'baz' from the second set
+    }
+    ```
+
+    :::
   */
   recursiveUpdateUntil =
-    # Predicate, taking the path to the current attribute as a list of strings for attribute names, and the two values at that path from the original arguments.
     pred:
-    # Left attribute set of the merge.
     lhs:
-    # Right attribute set of the merge.
     rhs:
     let f = attrPath:
       zipAttrsWith (n: values:
@@ -971,51 +1545,90 @@ rec {
     in f [] [rhs lhs];
 
 
-  /* A recursive variant of the update operator ‘//’.  The recursion
-     stops when one of the attribute values is not an attribute set,
-     in which case the right hand side value takes precedence over the
-     left hand side value.
+  /**
+    A recursive variant of the update operator ‘//’.  The recursion
+    stops when one of the attribute values is not an attribute set,
+    in which case the right hand side value takes precedence over the
+    left hand side value.
+
+
+    # Inputs
+
+    `lhs`
+
+    : Left attribute set of the merge.
+
+    `rhs`
+
+    : Right attribute set of the merge.
+
+    # Type
+
+    ```
+    recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
+    ```
 
-     Example:
-       recursiveUpdate {
-         boot.loader.grub.enable = true;
-         boot.loader.grub.device = "/dev/hda";
-       } {
-         boot.loader.grub.device = "";
-       }
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.recursiveUpdate` usage example
 
-       returns: {
-         boot.loader.grub.enable = true;
-         boot.loader.grub.device = "";
-       }
+    ```nix
+    recursiveUpdate {
+      boot.loader.grub.enable = true;
+      boot.loader.grub.device = "/dev/hda";
+    } {
+      boot.loader.grub.device = "";
+    }
+
+    returns: {
+      boot.loader.grub.enable = true;
+      boot.loader.grub.device = "";
+    }
+    ```
 
-     Type:
-       recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
+    :::
   */
   recursiveUpdate =
-    # Left attribute set of the merge.
     lhs:
-    # Right attribute set of the merge.
     rhs:
     recursiveUpdateUntil (path: lhs: rhs: !(isAttrs lhs && isAttrs rhs)) lhs rhs;
 
 
-  /*
+  /**
     Recurse into every attribute set of the first argument and check that:
     - Each attribute path also exists in the second argument.
     - If the attribute's value is not a nested attribute set, it must have the same value in the right argument.
 
-     Example:
-       matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
-       => true
 
-     Type:
-       matchAttrs :: AttrSet -> AttrSet -> Bool
+    # Inputs
+
+    `pattern`
+
+    : Attribute set structure to match
+
+    `attrs`
+
+    : Attribute set to check
+
+    # Type
+
+    ```
+    matchAttrs :: AttrSet -> AttrSet -> Bool
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.matchAttrs` usage example
+
+    ```nix
+    matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
+    => true
+    ```
+
+    :::
   */
   matchAttrs =
-    # Attribute set structure to match
     pattern:
-    # Attribute set to check
     attrs:
     assert isAttrs pattern;
     all
@@ -1034,161 +1647,340 @@ rec {
     )
     (attrNames pattern);
 
-  /* Override only the attributes that are already present in the old set
+  /**
+    Override only the attributes that are already present in the old set
     useful for deep-overriding.
 
-    Example:
-      overrideExisting {} { a = 1; }
-      => {}
-      overrideExisting { b = 2; } { a = 1; }
-      => { b = 2; }
-      overrideExisting { a = 3; b = 2; } { a = 1; }
-      => { a = 1; b = 2; }
 
-    Type:
-      overrideExisting :: AttrSet -> AttrSet -> AttrSet
+    # Inputs
+
+    `old`
+
+    : Original attribute set
+
+    `new`
+
+    : Attribute set with attributes to override in `old`.
+
+    # Type
+
+    ```
+    overrideExisting :: AttrSet -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.overrideExisting` usage example
+
+    ```nix
+    overrideExisting {} { a = 1; }
+    => {}
+    overrideExisting { b = 2; } { a = 1; }
+    => { b = 2; }
+    overrideExisting { a = 3; b = 2; } { a = 1; }
+    => { a = 1; b = 2; }
+    ```
+
+    :::
   */
   overrideExisting =
-    # Original attribute set
     old:
-    # Attribute set with attributes to override in `old`.
     new:
     mapAttrs (name: value: new.${name} or value) old;
 
 
-  /* Turns a list of strings into a human-readable description of those
+  /**
+    Turns a list of strings into a human-readable description of those
     strings represented as an attribute path. The result of this function is
     not intended to be machine-readable.
     Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
 
-    Example:
-      showAttrPath [ "foo" "10" "bar" ]
-      => "foo.\"10\".bar"
-      showAttrPath []
-      => "<root attribute path>"
 
-    Type:
-      showAttrPath :: [String] -> String
+    # Inputs
+
+    `path`
+
+    : Attribute path to render to a string
+
+    # Type
+
+    ```
+    showAttrPath :: [String] -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.showAttrPath` usage example
+
+    ```nix
+    showAttrPath [ "foo" "10" "bar" ]
+    => "foo.\"10\".bar"
+    showAttrPath []
+    => "<root attribute path>"
+    ```
+
+    :::
   */
   showAttrPath =
-    # Attribute path to render to a string
     path:
     if path == [] then "<root attribute path>"
     else concatMapStringsSep "." escapeNixIdentifier path;
 
 
-  /* Get a package output.
-     If no output is found, fallback to `.out` and then to the default.
+  /**
+    Get a package output.
+    If no output is found, fallback to `.out` and then to the default.
+
+
+    # Inputs
+
+    `output`
 
-     Example:
-       getOutput "dev" pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
+    : 1\. Function argument
 
-     Type:
-       getOutput :: String -> Derivation -> String
+    `pkg`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    getOutput :: String -> Derivation -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getOutput` usage example
+
+    ```nix
+    getOutput "dev" pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
+    ```
+
+    :::
   */
   getOutput = output: pkg:
     if ! pkg ? outputSpecified || ! pkg.outputSpecified
       then pkg.${output} or pkg.out or pkg
       else pkg;
 
-  /* Get a package's `bin` output.
-     If the output does not exist, fallback to `.out` and then to the default.
+  /**
+    Get a package's `bin` output.
+    If the output does not exist, fallback to `.out` and then to the default.
+
+    # Inputs
+
+    `pkg`
 
-     Example:
-       getBin pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r"
+    : The package whose `bin` output will be retrieved.
 
-     Type:
-       getBin :: Derivation -> String
+    # Type
+
+    ```
+    getBin :: Derivation -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getBin` usage example
+
+    ```nix
+    getBin pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r"
+    ```
+
+    :::
   */
   getBin = getOutput "bin";
 
 
-  /* Get a package's `lib` output.
-     If the output does not exist, fallback to `.out` and then to the default.
+  /**
+    Get a package's `lib` output.
+    If the output does not exist, fallback to `.out` and then to the default.
+
+    # Inputs
+
+    `pkg`
 
-     Example:
-       getLib pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-lib"
+    : The package whose `lib` output will be retrieved.
 
-     Type:
-       getLib :: Derivation -> String
+    # Type
+
+    ```
+    getLib :: Derivation -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getLib` usage example
+
+    ```nix
+    getLib pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-lib"
+    ```
+
+    :::
   */
   getLib = getOutput "lib";
 
 
-  /* Get a package's `dev` output.
-     If the output does not exist, fallback to `.out` and then to the default.
+  /**
+    Get a package's `dev` output.
+    If the output does not exist, fallback to `.out` and then to the default.
+
+    # Inputs
+
+    `pkg`
 
-     Example:
-       getDev pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
+    : The package whose `dev` output will be retrieved.
+
+    # Type
+
+    ```
+    getDev :: Derivation -> String
+    ```
 
-     Type:
-       getDev :: Derivation -> String
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getDev` usage example
+
+    ```nix
+    getDev pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
+    ```
+
+    :::
   */
   getDev = getOutput "dev";
 
 
-  /* Get a package's `man` output.
-     If the output does not exist, fallback to `.out` and then to the default.
+  /**
+    Get a package's `man` output.
+    If the output does not exist, fallback to `.out` and then to the default.
+
+    # Inputs
+
+    `pkg`
+
+    : The package whose `man` output will be retrieved.
+
+    # Type
+
+    ```
+    getMan :: Derivation -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getMan` usage example
 
-     Example:
-       getMan pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-man"
+    ```nix
+    getMan pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-man"
+    ```
 
-     Type:
-       getMan :: Derivation -> String
+    :::
   */
   getMan = getOutput "man";
 
-  /* Pick the outputs of packages to place in `buildInputs`
+  /**
+    Pick the outputs of packages to place in `buildInputs`
+
+    # Inputs
 
-   Type: chooseDevOutputs :: [Derivation] -> [String]
+    `pkgs`
 
+    : List of packages.
+
+    # Type
+
+    ```
+    chooseDevOutputs :: [Derivation] -> [String]
+    ```
   */
   chooseDevOutputs = builtins.map getDev;
 
-  /* Make various Nix tools consider the contents of the resulting
-     attribute set when looking for what to build, find, etc.
+  /**
+    Make various Nix tools consider the contents of the resulting
+    attribute set when looking for what to build, find, etc.
 
-     This function only affects a single attribute set; it does not
-     apply itself recursively for nested attribute sets.
+    This function only affects a single attribute set; it does not
+    apply itself recursively for nested attribute sets.
 
-     Example:
-       { pkgs ? import <nixpkgs> {} }:
-       {
-         myTools = pkgs.lib.recurseIntoAttrs {
-           inherit (pkgs) hello figlet;
-         };
-       }
 
-     Type:
-       recurseIntoAttrs :: AttrSet -> AttrSet
+    # Inputs
+
+    `attrs`
+
+    : An attribute set to scan for derivations.
+
+    # Type
 
-   */
+    ```
+    recurseIntoAttrs :: AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.recurseIntoAttrs` usage example
+
+    ```nix
+    { pkgs ? import <nixpkgs> {} }:
+    {
+      myTools = pkgs.lib.recurseIntoAttrs {
+        inherit (pkgs) hello figlet;
+      };
+    }
+    ```
+
+    :::
+  */
   recurseIntoAttrs =
-    # An attribute set to scan for derivations.
     attrs:
     attrs // { recurseForDerivations = true; };
 
-  /* Undo the effect of recurseIntoAttrs.
+  /**
+    Undo the effect of recurseIntoAttrs.
 
-     Type:
-       dontRecurseIntoAttrs :: AttrSet -> AttrSet
-   */
+
+    # Inputs
+
+    `attrs`
+
+    : An attribute set to not scan for derivations.
+
+    # Type
+
+    ```
+    dontRecurseIntoAttrs :: AttrSet -> AttrSet
+    ```
+  */
   dontRecurseIntoAttrs =
-    # An attribute set to not scan for derivations.
     attrs:
     attrs // { recurseForDerivations = false; };
 
-  /* `unionOfDisjoint x y` is equal to `x // y // z` where the
-     attrnames in `z` are the intersection of the attrnames in `x` and
-     `y`, and all values `assert` with an error message.  This
-      operator is commutative, unlike (//).
+  /**
+    `unionOfDisjoint x y` is equal to `x // y // z` where the
+    attrnames in `z` are the intersection of the attrnames in `x` and
+    `y`, and all values `assert` with an error message.  This
+     operator is commutative, unlike (//).
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
 
-     Type: unionOfDisjoint :: AttrSet -> AttrSet -> AttrSet
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    unionOfDisjoint :: AttrSet -> AttrSet -> AttrSet
+    ```
   */
   unionOfDisjoint = x: y:
     let