I want to thank all of those who contributed to this thread. If I can summarize the contributions (feel free to clarify any misrepresentations):
I'm intrigued by the idea mentioned in this last bullet point. Is this functional equivalent of Prolog's difference lists -- essentially partial data structures that are grown top-down rather than bottom-up, actually efficient? Is there an overhead penalty to be paid for using functions here, or is it compiled away into Prolog-like tail calls that fill in the missing parts of the data structure?

Todd Wilson

On Thu, Mar 16, 2023 at 6:33 PM Todd Wilson <twilson@csufresno.edu> wrote:
Dear Cafe,

Here's a basic exercise in list processing: define a function
runs :: Ord a => [a] -> [[a]]
that breaks up its input list into a list of increasing "runs"; e.g.,
runs [3,4,5,6,2,3,4,1,2,1]  --->  [[3,4,5,6],[2,3,4],[1,2],[1]]
A natural solution is the following:
runs [] = []
runs (x:xs) = let (ys, zs) = run x xs
              in (x:ys) : runs zs
  where
    run x [] = ([], [])
    run x (y:ys) = if x <= y
                   then let (us, vs) = run y ys
                        in (y:us, vs)
                   else ([], y:ys)
My question: can we do better than this? It seems that this solution is constantly building and breaking apart pairs. (Or is it, when optimized?)

Todd Wilson