summary refs log tree commit diff
path: root/lib/fixed-points.nix
diff options
context:
space:
mode:
authorWill Fancher <elvishjerricco@gmail.com>2017-07-13 18:54:04 -0400
committerWill Fancher <elvishjerricco@gmail.com>2017-07-14 06:43:33 -0400
commit05f9db601abd582be51f096affbb97eff49f2ccb (patch)
tree579844c1a85d948cc45b9f1c3061ea0b89cf4557 /lib/fixed-points.nix
parent8b764960e93f60cb0896a8866f8e53e331726985 (diff)
downloadnixpkgs-05f9db601abd582be51f096affbb97eff49f2ccb.tar
nixpkgs-05f9db601abd582be51f096affbb97eff49f2ccb.tar.gz
nixpkgs-05f9db601abd582be51f096affbb97eff49f2ccb.tar.bz2
nixpkgs-05f9db601abd582be51f096affbb97eff49f2ccb.tar.lz
nixpkgs-05f9db601abd582be51f096affbb97eff49f2ccb.tar.xz
nixpkgs-05f9db601abd582be51f096affbb97eff49f2ccb.tar.zst
nixpkgs-05f9db601abd582be51f096affbb97eff49f2ccb.zip
Added `self` views of the interface in `makeExtensibleWithInterface`
Fixing the `overrideScope` in `haskellpackages`.
Diffstat (limited to 'lib/fixed-points.nix')
-rw-r--r--lib/fixed-points.nix43
1 files changed, 29 insertions, 14 deletions
diff --git a/lib/fixed-points.nix b/lib/fixed-points.nix
index 5039a45cc3f..910dd24b202 100644
--- a/lib/fixed-points.nix
+++ b/lib/fixed-points.nix
@@ -71,19 +71,34 @@ rec {
 
   # Same as `makeExtensible` but the name of the extending attribute is
   # customized.
-  makeExtensibleWithCustomName = extenderName: makeExtensibleWithInterface
-    (fixedPoint: extend: fixedPoint // { ${extenderName} = extend; });
+  makeExtensibleWithCustomName = extenderName: f: makeExtensibleWithInterface
+    (fixedPoint: extend: fixedPoint // { ${extenderName} = ext: extend (_: ext); })
+    (_: f);
 
-  # Similar to `makeExtensible`, but expects you to implement the
-  # final interface for the result. Specifically, it takes an extra
-  # argument: a function that takes the final result and the `extend`
-  # function as arguments, and returns a transformed result
-  # (preferably one that contains the `extend` function). This is
-  # mainly useful for getting to choose what to name the `extend`
-  # function in the resulting attribute set. But it's also useful for
-  # having an internal structure that extensions can see, but the user
-  # facing code cannot.
-  makeExtensibleWithInterface = interface: fext: interface
-    (fix' fext)
-    (f: makeExtensibleWithInterface interface (extends f fext));
+  # A version of `makeExtensible` that allows the function being fixed
+  # to return a different interface than the interface returned to the
+  # user. Along with `self` and `super` views of the internal
+  # interface, a `self` view of the output interface is also
+  # provided. `extend` is not added to the output by default. This is
+  # the job of the interface.
+  #
+  #     nix-repl> foo = {a, b}: {c = a + b;}
+  #
+  #     nix-repl> interface = {args, val, ...}: extend: val // {inherit extend;}
+  #
+  #     nix-repl> obj = makeExtensibleWithInterface interface (output: self: { args = {a = 1; b = 2;}; val = foo self.args; })
+  #
+  #     nix-repl> obj.c
+  #     3
+  #
+  #     nix-repl> obj = obj.extend (output: self: super: { args = super.args // { b = output.d; }; })
+  #
+  #     nix-repl> obj = obj.extend (output: self: super: { val = super.val // { d = 10; }; })
+  #
+  #     nix-repl> { inherit (obj) c d; }
+  #     { c = 11; d = 10; }
+  makeExtensibleWithInterface = interface: f: let i = interface
+    (fix' (f i))
+    (fext: makeExtensibleWithInterface interface (i': (extends (fext i') (f i'))));
+  in i;
 }