The way I would approach this is to write what essentially amounts to a declarative specification of what computation needs to be run, and then define an interpreter that handles the caching of intermediate values.
The "Embedded DSL + Interpreter" pattern is incredibly powerful, and it's nice to see it catching on more.
The "Embedded DSL + Interpreter" pattern is incredibly powerful, and it's nice to see it catching on more.