about summary refs log tree commit diff
path: root/lib/fixed-points.nix
diff options
context:
space:
mode:
authorSilvan Mosberger <silvan.mosberger@tweag.io>2023-09-28 17:21:34 +0200
committerSilvan Mosberger <silvan.mosberger@tweag.io>2023-09-28 17:21:34 +0200
commit13c278cb1cd8503f5ab9a550315a75a0001bc247 (patch)
tree54d39aae172c615c1e74a25e017d50236ccc62fc /lib/fixed-points.nix
parent149a793c07e07965c8941658e59056d11a010668 (diff)
lib.fixedPoints.extends: Doc improvements
Co-Authored-By: Valentin Gagarin <valentin.gagarin@tweag.io>
Diffstat (limited to 'lib/fixed-points.nix')
-rw-r--r--lib/fixed-points.nix83
1 files changed, 71 insertions, 12 deletions
diff --git a/lib/fixed-points.nix b/lib/fixed-points.nix
index 9020fa5f35557..52e0879bf9ffc 100644
--- a/lib/fixed-points.nix
+++ b/lib/fixed-points.nix
@@ -53,12 +53,55 @@ rec {
       else converge f x';
 
   /*
-    `extends overlay f` applies the overlay `overlay` to the fixed-point function `f` to get a new fixed-point function.
+    Extend a function using an overlay.
+
     Overlays allow modifying and extending fixed-point functions, specifically ones returning attribute sets.
+    A fixed-point function is a function which is intended to be evaluated by passing the result of itself as the argument.
+    This is possible due to Nix's lazy evaluation.
+
+
+    A fixed-point function returning an attribute set has the form
 
-    A fixed-point function is a function which is intended to be evaluated by passing the result of itself as the argument, only possible due to Nix's lazy evaluation.
-    Here's an example of one:
+    ```nix
+    final: { # attributes }
     ```
+
+    where `final` refers to the lazily evaluated attribute set returned by the fixed-point function.
+
+    An overlay to such a fixed-point function has the form
+
+    ```nix
+    final: prev: { # attributes }
+    ```
+
+    where `prev` refers to the result of the original function to `final`, and `final` is the result of the composition of the overlay and the original function.
+
+    Applying an overlay is done with `extends`:
+
+    ```nix
+    let
+      f = final: { # attributes };
+      overlay = final: prev: { # attributes };
+    in extends overlay f;
+    ```
+
+    To get the value of `final`, use `lib.fix`:
+
+    ```nix
+    let
+      f = final: { # attributes };
+      overlay = final: prev: { # attributes };
+      g = extends overlay f;
+    in fix g
+    ```
+
+    :::{.example}
+
+    # Extend a fixed-point function with an overlay
+
+    Define a fixed-point function `f` that expects its own output as the argument `final`:
+
+    ```nix-repl
     f = final: {
       # Constant value a
       a = 1;
@@ -67,15 +110,18 @@ rec {
       b = final.a + 2;
     }
     ```
-    We can evaluated this using [`lib.fix`](#function-library-lib.fixedPoints.fix) to get the final result:
-    ```
+
+    Evaluate this using [`lib.fix`](#function-library-lib.fixedPoints.fix) to get the final result:
+
+    ```nix-repl
     fix f
     => { a = 1; b = 3; }
     ```
 
     An overlay represents a modification or extension of such a fixed-point function.
     Here's an example of an overlay:
-    ```
+
+    ```nix-repl
     overlay = final: prev: {
       # Modify the previous value of a, available as prev.a
       a = prev.a + 10;
@@ -85,13 +131,17 @@ rec {
     }
     ```
 
-    We can now use `extends overlay f` to apply the overlay to the fixed-point function `f`, giving us a new fixed-point function `g` with the combined behavior of `f` and `overlay`.
-    ```
+    Use `extends overlay f` to apply the overlay to the fixed-point function `f`.
+    This produces a new fixed-point function `g` with the combined behavior of `f` and `overlay`:
+
+    ```nix-repl
     g = extends overlay f
     ```
+
     The result is a function, so we can't print it directly, but it's the same as:
-    ```
-    g = final: {
+
+    ```nix-repl
+    g' = final: {
       # The constant from f, but changed with the overlay
       a = 1 + 10;
 
@@ -103,11 +153,13 @@ rec {
     }
     ```
 
-    We can evaluate this using [`lib.fix`](#function-library-lib.fixedPoints.fix) again to get the final result:
-    ```
+    Evaluate this using [`lib.fix`](#function-library-lib.fixedPoints.fix) again to get the final result:
+
+    ```nix-repl
     fix g
     => { a = 11; b = 13; c = 24; }
     ```
+    :::
 
     Type:
       extends :: (Attrs -> Attrs -> Attrs) # The overlay to apply to the fixed-point function
@@ -128,6 +180,13 @@ rec {
 
       fix (extends (final: prev: { c = final.a + final.b; }) f)
       => { a = 1; b = 3; c = 4; }
+
+    :::{.note}
+    The argument to the given fixed-point function after applying an overlay will *not* refer to its own return value, but rather to the value after evaluating the overlay function.
+
+    The given fixed-point function is called with a separate argument than if it was evaluated with `lib.fix`.
+    The new argument
+    :::
   */
   extends =
     # The overlay to apply to the fixed-point function