Co-recursion is a principled way to turn a top-down algorithm into a bottom-up one. For instance, in Haskell, it's easy to write the fibonacci series from its definition:
fibonacci 0 = 1
fibonacci 1 = 1
fibonacci n = fibonacci (n - 1) + fibonacci (n - 2)
But this is ridiculously inefficient. Until now, the only "principled" way I knew of to transform this into something sensible was through memoization, but that's still very wasteful.With co-recursion in my toolkit, I can transform this into a form that generates the whole series as a stream:
fibonacci_series = 0: 1: more fibonacci_series
where
more f1: rest@(f2: _) = f1 + f2: more(rest)
And thanks to Haskell's lazy, garbage collected semantics, taking the nth element of the series (remembering to drop data I don't need) turns out to be equivalent to: fibonacci n = fib n 0 1
where
fib 0 a b = a
fib n a b = fib (n-1) b (a+b)
Which is what we wanted. :-)