Lazily consuming a self-referential linked list
VegOwOtenks:
The order is like this because it allows the list that is build-up to travel-backwards along the computation, like it would with TardisT. This enables cheap list-building (only cons, no concatenation) while preserving FIFO semantics.
Ah I see, that pretty neat! And beyond my skill level xD.
I’ve had a bit more of a look and the circle I’m trying to square is the (q → s →[q] → ([q],s)) function. The question is where do you get this q element from if [q] is empty?
A minor change to the type signature to make it (s → [q] → (s, [q])) means then this function can also have some resposible logic for determining when to stop processing.
run3 s0 [] _ = s0 -- queue is empty stop processing
run3 s0 (q:qs) f = let
(s1, newQ) = f s0 q
in run3 s1 (newQ ++ qs) f
-- | swap the order of the (++) and `use reverse` to get LIFO/FIFO behaviour
test2 initState queue = run3 initState queue someFunc
where someFunc s qElem
-- | some rock solid cases that stops new list elements being generated indefinitely
I’m not totally sure if that’s helpful as I’m struggling to grasp the behaviour of Tardis.
Part of me feels like this is also achievable with nested foldl/foldrs but I haven’t looked that far into it.
Sorry I couldn’t help more!
Discussion in the ATmosphere