···1{ lib, ... }:
2rec {
3- # Compute the fixed point of the given function `f`, which is usually an
4- # attribute set that expects its final, non-recursive representation as an
5- # argument:
6- #
7- # f = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }
8- #
9- # Nix evaluates this recursion until all references to `self` have been
10- # resolved. At that point, the final result is returned and `f x = x` holds:
11- #
12- # nix-repl> fix f
13- # { bar = "bar"; foo = "foo"; foobar = "foobar"; }
14- #
15- # Type: fix :: (a -> a) -> a
16- #
17- # See https://en.wikipedia.org/wiki/Fixed-point_combinator for further
18- # details.
00000019 fix = f: let x = f x; in x;
2021- # A variant of `fix` that records the original recursive attribute set in the
22- # result. This is useful in combination with the `extends` function to
23- # implement deep overriding. See pkgs/development/haskell-modules/default.nix
24- # for a concrete example.
00025 fix' = f: let x = f x // { __unfix__ = f; }; in x;
2627- # Return the fixpoint that `f` converges to when called recursively, starting
28- # with the input `x`.
29- #
30- # nix-repl> converge (x: x / 2) 16
31- # 0
00000032 converge = f: x:
33 let
34 x' = f x;
···37 then x
38 else converge f x';
3940- # Modify the contents of an explicitly recursive attribute set in a way that
41- # honors `self`-references. This is accomplished with a function
42- #
43- # g = self: super: { foo = super.foo + " + "; }
44- #
45- # that has access to the unmodified input (`super`) as well as the final
46- # non-recursive representation of the attribute set (`self`). `extends`
47- # differs from the native `//` operator insofar as that it's applied *before*
48- # references to `self` are resolved:
49- #
50- # nix-repl> fix (extends g f)
51- # { bar = "bar"; foo = "foo + "; foobar = "foo + bar"; }
52- #
53- # The name of the function is inspired by object-oriented inheritance, i.e.
54- # think of it as an infix operator `g extends f` that mimics the syntax from
55- # Java. It may seem counter-intuitive to have the "base class" as the second
56- # argument, but it's nice this way if several uses of `extends` are cascaded.
57- #
58- # To get a better understanding how `extends` turns a function with a fix
59- # point (the package set we start with) into a new function with a different fix
60- # point (the desired packages set) lets just see, how `extends g f`
61- # unfolds with `g` and `f` defined above:
62- #
63- # extends g f = self: let super = f self; in super // g self super;
64- # = self: let super = { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }; in super // g self super
65- # = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } // g self { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }
66- # = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } // { foo = "foo" + " + "; }
67- # = self: { foo = "foo + "; bar = "bar"; foobar = self.foo + self.bar; }
68- #
000000069 extends = f: rattrs: self: let super = rattrs self; in super // f self super;
7071- # Compose two extending functions of the type expected by 'extends'
72- # into one where changes made in the first are available in the
73- # 'super' of the second
0074 composeExtensions =
75 f: g: final: prev:
76 let fApplied = f final prev;
77 prev' = prev // fApplied;
78 in fApplied // g final prev';
7980- # Compose several extending functions of the type expected by 'extends' into
81- # one where changes made in preceding functions are made available to
82- # subsequent ones.
83- #
84- # composeManyExtensions : [packageSet -> packageSet -> packageSet] -> packageSet -> packageSet -> packageSet
85- # ^final ^prev ^overrides ^final ^prev ^overrides
000086 composeManyExtensions =
87 lib.foldr (x: y: composeExtensions x y) (final: prev: {});
8889- # Create an overridable, recursive attribute set. For example:
90- #
91- # nix-repl> obj = makeExtensible (self: { })
92- #
93- # nix-repl> obj
94- # { __unfix__ = «lambda»; extend = «lambda»; }
95- #
96- # nix-repl> obj = obj.extend (self: super: { foo = "foo"; })
97- #
98- # nix-repl> obj
99- # { __unfix__ = «lambda»; extend = «lambda»; foo = "foo"; }
100- #
101- # nix-repl> obj = obj.extend (self: super: { foo = super.foo + " + "; bar = "bar"; foobar = self.foo + self.bar; })
102- #
103- # nix-repl> obj
104- # { __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; }
0000105 makeExtensible = makeExtensibleWithCustomName "extend";
106107- # Same as `makeExtensible` but the name of the extending attribute is
108- # customized.
00109 makeExtensibleWithCustomName = extenderName: rattrs:
110 fix' (self: (rattrs self) // {
111 ${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs);
···1{ lib, ... }:
2rec {
3+ /*
4+ Compute the fixed point of the given function `f`, which is usually an
5+ attribute set that expects its final, non-recursive representation as an
6+ argument:
7+8+ ```
9+ f = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }
10+ ```
11+12+ Nix evaluates this recursion until all references to `self` have been
13+ resolved. At that point, the final result is returned and `f x = x` holds:
14+15+ ```
16+ nix-repl> fix f
17+ { bar = "bar"; foo = "foo"; foobar = "foobar"; }
18+ ```
19+20+ Type: fix :: (a -> a) -> a
21+22+ See https://en.wikipedia.org/wiki/Fixed-point_combinator for further
23+ details.
24+ */
25 fix = f: let x = f x; in x;
2627+ /*
28+ A variant of `fix` that records the original recursive attribute set in the
29+ result, in an attribute named `__unfix__`.
30+31+ This is useful in combination with the `extends` function to
32+ implement deep overriding.
33+ */
34 fix' = f: let x = f x // { __unfix__ = f; }; in x;
3536+ /*
37+ Return the fixpoint that `f` converges to when called iteratively, starting
38+ with the input `x`.
39+40+ ```
41+ nix-repl> converge (x: x / 2) 16
42+ 0
43+ ```
44+45+ Type: (a -> a) -> a -> a
46+ */
47 converge = f: x:
48 let
49 x' = f x;
···52 then x
53 else converge f x';
5455+ /*
56+ Modify the contents of an explicitly recursive attribute set in a way that
57+ honors `self`-references. This is accomplished with a function
58+59+ ```nix
60+ g = self: super: { foo = super.foo + " + "; }
61+ ```
62+63+ that has access to the unmodified input (`super`) as well as the final
64+ non-recursive representation of the attribute set (`self`). `extends`
65+ differs from the native `//` operator insofar as that it's applied *before*
66+ references to `self` are resolved:
67+68+ ```
69+ nix-repl> fix (extends g f)
70+ { bar = "bar"; foo = "foo + "; foobar = "foo + bar"; }
71+ ```
72+73+ The name of the function is inspired by object-oriented inheritance, i.e.
74+ think of it as an infix operator `g extends f` that mimics the syntax from
75+ Java. It may seem counter-intuitive to have the "base class" as the second
76+ argument, but it's nice this way if several uses of `extends` are cascaded.
77+78+ To get a better understanding how `extends` turns a function with a fix
79+ point (the package set we start with) into a new function with a different fix
80+ point (the desired packages set) lets just see, how `extends g f`
81+ unfolds with `g` and `f` defined above:
82+83+ ```
84+ extends g f = self: let super = f self; in super // g self super;
85+ = self: let super = { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }; in super // g self super
86+ = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } // g self { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }
87+ = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } // { foo = "foo" + " + "; }
88+ = self: { foo = "foo + "; bar = "bar"; foobar = self.foo + self.bar; }
89+ ```
90+ */
91 extends = f: rattrs: self: let super = rattrs self; in super // f self super;
9293+ /*
94+ Compose two extending functions of the type expected by 'extends'
95+ into one where changes made in the first are available in the
96+ 'super' of the second
97+ */
98 composeExtensions =
99 f: g: final: prev:
100 let fApplied = f final prev;
101 prev' = prev // fApplied;
102 in fApplied // g final prev';
103104+ /*
105+ Compose several extending functions of the type expected by 'extends' into
106+ one where changes made in preceding functions are made available to
107+ subsequent ones.
108+109+ ```
110+ composeManyExtensions : [packageSet -> packageSet -> packageSet] -> packageSet -> packageSet -> packageSet
111+ ^final ^prev ^overrides ^final ^prev ^overrides
112+ ```
113+ */
114 composeManyExtensions =
115 lib.foldr (x: y: composeExtensions x y) (final: prev: {});
116117+ /*
118+ Create an overridable, recursive attribute set. For example:
119+120+ ```
121+ nix-repl> obj = makeExtensible (self: { })
122+123+ nix-repl> obj
124+ { __unfix__ = «lambda»; extend = «lambda»; }
125+126+ nix-repl> obj = obj.extend (self: super: { foo = "foo"; })
127+128+ nix-repl> obj
129+ { __unfix__ = «lambda»; extend = «lambda»; foo = "foo"; }
130+131+ nix-repl> obj = obj.extend (self: super: { foo = super.foo + " + "; bar = "bar"; foobar = self.foo + self.bar; })
132+133+ nix-repl> obj
134+ { __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; }
135+ ```
136+ */
137 makeExtensible = makeExtensibleWithCustomName "extend";
138139+ /*
140+ Same as `makeExtensible` but the name of the extending attribute is
141+ customized.
142+ */
143 makeExtensibleWithCustomName = extenderName: rattrs:
144 fix' (self: (rattrs self) // {
145 ${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs);