I’m trying to use lazy streams from https://github.com/ptarau/AnswerStreamGenerators to implement a simple example, in which first stream of nats is offset by some number, then the two streams are added up. I tried:
nat(N), drop(3, N, N1), sum(N, N1, S), show(3, S). % [3, 4, 5].
(The result I was expecting was [0,1,2]+[3,4,5]=[3,5,7]
).
I looked under the hood of lazy_streams and I realized that all streams are actually “destructive”, so even a simple show
advances the stream forward. What confuses me a bit is the drop/3 predicate, which implies that the original stream is left untouched as it returns another stream.
How can I implement this example with the lazy_streams library?
I also tried to play a bit with delimited continuations to implement lazy streams:
ask(El, Stream, Stream2) :- reset(Stream, El, Stream2).
take(0, _, []) :- !.
take(N, Stream, List) :-
reset(Stream, El, Cont),
(Cont = 0 -> List = [] ; succ(N1, N), take(N1, Cont, Rest), List = [El | Rest]).
drop(0, S, S) :- !.
drop(N, Stream, Stream2) :- succ(N1, N), ask(_, Stream, Stream1), drop(N1, Stream1, Stream2).
nat(From) :- shift(From), succ(From, From1), nat(From1).
map2(Predicate, S1, S2) :- ask(X, S1, E1), ask(Y, S2, E2),
((E1 = 0 ; E2 = 0) -> true ; call(Predicate, X, Y, Result), shift(Result), map2(Predicate, E1, E2)).
Using this ad-hoc implementation I was able to solve my contrived example:
N = nat(0), drop(3, N, N1), take(3, map2(plus, N, N1), L). % L = [3, 5, 7]
My second question is: is there some prior art on lazy streams using delimited continuations and why haven’t the authors of lazy_streams used them instead?