Thu May 16 08:34:28 EDT 2019

Use the fold

Curious, because I have never done it like this.  It looks reasonable

Start with a no-op:

fuse' p = foldProgram letPrim letLoop cons nil where
  nil = []
  cons a b = a:b
  letPrim c cs = LetPrim c cs
  letLoop i fs = LetLoop i fs

To do the fuse, it can be done in two spots: either as part of cons on
a per element basis, or as part of letLoop, operating on the whole

Let's try cons first.

I got to this, which only does one layer.  Why is that?  Aha because
it uses a non-recursive cons.

fuse' p = Program $ foldProgram LetPrim LetLoop cons [] p where
  cons h@(LetLoop i as) t@((LetLoop i0 bs):t') =
    case i == i0 of
      True  -> (LetLoop i (as ++ bs)) : t'
      False -> h:t
  cons a b = a:b

This is a lot more tricky than I thought.  The fully recursive routine
needs a cons that is non-recursive.

OK I see now: it works inside out, and fusion is an outside-in
operation: when the outside is fused, it exposes fusable insides.
Running the operation multiple times does produce the correct result.

So, is it possible to create a fold that is top-down?

That is a breath-first iteration pattern.