
On 23 December 2010 21:12, Stephen Tetley
I'd go with direct recursion for this one - the pattern of consumption and production that generates the answer doesn't seem to neatly match any of the standard recursion combinators (map, unfold, fold, mapAccum, ...) nor exotic ones (skipping streams c.f. the Stream fusion paper, apomorphisms, ...).
Here's a synthesized functional that matches the needed behaviour. It takes from: a) apomorphism - has a final flush operation b) skipping streams (the Stream fusion paper) - a skipping Next case, though in this case there is no Done c) unfoldMap - itself a synthetic combination of unfold and map, which is unfolding against a list as well as state (the unfold equivalent of mapAccumL). Unimaginatively I've called it "lessproductive" as it can produce less than it consumes, though as it has no Done it must consume everything... data Step st a = Yield a !st | Next !st lessproductive :: (st -> a -> Step st b) -> (st -> b) -> st -> [a] -> [b] lessproductive phi flush = step where step st [] = [flush st] step st (x:xs) = case phi st x of Next st' -> step st' xs Yield b st' -> b : step st' xs ranges :: (Num a, Eq a) => [a] -> [(a,a)] ranges [] = [] ranges (x:xs) = lessproductive phi id (x,x) xs where phi (i,j) n | j+1 == n = Next (i,n) phi ans n = Yield ans (n,n)