Yes, this is correct. Though it's worth noting that this is not some transformation being done by the compiler, but an emergent property of the interaction net.
find_min_and_subtract([H], [R], Min) :-
Min = H,
R is H - Min.
find_min_and_subtract([H|T], [R|Rs], Min) :-
find_min_and_subtract(T, Rs, TailMin),
(H < TailMin -> Min = H ; Min = TailMin),
R is H - Min,!.
Which [9,4,12,2] -> [7, 2, 10, 0].But this doesn't work for all cases anyway (just the ones where the last value is also the minimum). I feel it can be fully expressed in one pass with miniKanren instead but no time to figure that out now; it can defer the arithmetic by setting up constraints.
Always liked the idea of 'using variables in the past' (or creating them in the future) and the first amazement moment was with Prolog (there were quite a lot of wow! moments in Prolog for the young me who only knew basic, pascal & c, like when you have some 'write multiply in prolog', when you deliver f(x,y)=x*y, you can not only do f(2,3) and get 6, but also f(2,y)=6 and get y=3), but, so it made me think of it.
:- use_module(library(clpfd)).
min(Min, Y, Min) :- Min #=< Y, !.
min(X, Min, Min) :- Min #=< X.
find_min_and_subtract_([], [], Min, Min).
find_min_and_subtract_([H|T], [R|Rs], TempMin, Min) :-
min(TempMin, H, NewTempMin),
R #= H - Min,
find_min_and_subtract_(T, Rs, NewTempMin, Min).
find_min_and_subtract([H|Hs], Rs, Min) :-
find_min_and_subtract_([H|Hs], Rs, H, Min).
With that (and an additional variable for the temporary minimum) it works for me: ?- find_min_and_subtract([9,2,4,12], Rs, Min).
Min = 2,
Rs = [7, 0, 2, 10]
https://swish.swi-prolog.org/p/qgchfMfB.plIn the case where asynchrony was actually necessary, it seems like a great alternative to function coloring.
But whether you should actually use it for something like their `sub_min` example is highly dependent on how good the performance of their implementation is. Creating a graph of references rather than making two passes over an array of integers is not clearly faster ... or clearer, for that matter.
https://vine.dev/docs/features/inverse
I was long curious about interaction nets. Can someone confirm if Vine will automagically derive an algorithm for doing this with a single pass or it will do one pass in "forward mode", but once the minimum is resolved, follow it up with a second implicit "book keeping and variable re-resolution pass" that will be equivalent to an actual full second pass you'd get in an imperative language?
It is all very much reminiscent of programming in tensorflow 0.x.