On 23 December 2010 21:12, Stephen Tetley <stephen.tet...@gmail.com> wrote:
> 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)

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to