Let’s expand out the definitions of fix
and extends
and see.
extends = overlay: f: final:
let prev = f final; in prev // overlay final prev;
fix = f: let x = f x; in x;
So your expression can be reduced as follows:
let h = self: { a = 1000; b = self.a / 2; c = self.b / 2; d = self.c / 2; };
in
fix
(extends
(final: prev: { a = -10; b = prev.a; c = prev.b; d = prev.c; e = prev.d; })
h
)
(inlining fix
)
let h = self: { a = 1000; b = self.a / 2; c = self.b / 2; d = self.c / 2; };
in
(f: let x = f x; in x)
(extends
(final: prev: { a = -10; b = prev.a; c = prev.b; d = prev.c; e = prev.d; })
h
)
(beta reduction)
let h = self: { a = 1000; b = self.a / 2; c = self.b / 2; d = self.c / 2; };
in
let x =
extends
(final: prev: { a = -10; b = prev.a; c = prev.b; d = prev.c; e = prev.d; })
h
x;
in x
(inlining extends
)
let h = self: { a = 1000; b = self.a / 2; c = self.b / 2; d = self.c / 2; };
in
let x =
(overlay: f: final: let prev = f final; in prev // overlay final prev)
(final: prev: { a = -10; b = prev.a; c = prev.b; d = prev.c; e = prev.d; })
h
x;
in x
(beta reduction)
let h = self: { a = 1000; b = self.a / 2; c = self.b / 2; d = self.c / 2; };
in
let x =
let prev = h x;
in
prev // (final: prev: { a = -10; b = prev.a; c = prev.b; d = prev.c; e = prev.d; }) x prev);
in x
(another beta reduction)
let h = self: { a = 1000; b = self.a / 2; c = self.b / 2; d = self.c / 2; };
in
let x =
let prev = h x;
in
prev // { a = -10; b = prev.a; c = prev.b; d = prev.c; e = prev.d; };
in x
(inlining h
)
let x =
let prev = (self: { a = 1000; b = self.a / 2; c = self.b / 2; d = self.c / 2; }) x;
in
prev // { a = -10; b = prev.a; c = prev.b; d = prev.c; e = prev.d; };
in x
(beta reduction)
let x =
let prev = { a = 1000; b = x.a / 2; c = x.b / 2; d = x.c / 2; };
in
prev // { a = -10; b = prev.a; c = prev.b; d = prev.c; e = prev.d; };
in x
(consolidate the let
s so this is easier to look at)
let
prev = { a = 1000; b = x.a / 2; c = x.b / 2; d = x.c / 2; };
x = prev // { a = -10; b = prev.a; c = prev.b; d = prev.c; e = prev.d; };
in x
If you look at that expression, it should be easier to see without having to do a bunch more reduction steps why the final result is what it is. You have to bounce back and forth between prev
and x
several times to see what the values of the later attributes are, and that’s the value that overlays provide: they let you consume the final result of some attributes (as when prev
references x
here) alongside an intermediate result of others (as when x
references prev
).