> So when it crosses over the previous function...
# share-your-work
b
So when it crosses over the previous function, we must have a strategy for deciding which paths it travels without relying on history.
Probably impossible: unless you want to have a lot of fun doing it “wrong” on purpose! Consider the simple “plus” operator: given the output of a sum, how do “undo” the sum into its two input summands? There’s an infinite number of possibilities. Consequently, for example, in Perera et al.‘s “Functional Programs that Explain Their Work” (ICFP 2012, excerpted in screenshot), they record the original operands so you can undo the computation. Their goal is to rewind the computation in order to rebuild a minimal program required to produce the result, but the challenge is the same. (Their overall strategy is to use computation traces recorded during execution, the _T_‘s in the screenshot.)
Arithmetic aside, for many kinds of data structure operations, you can define lenses that produce reasonable backprop results; although these lenses usually have to be defined manually. And it also turns out you can backprop without traces, but you end up having to do some recomputation. See Mayer et al “Bidirectional Evaluation with Direct Manipulation for Details” (OOPSLA 2018, the attached screenshot is the heart of the approach and takes a bit to grok; see video. The two forward arrows ⇒ in the attached screenshot are recomputations.)