foldr/build relies on identifying the respective
functions and their rewrite rules, while stream fusion relies on
recognizing the constructors involved.
Ah, I think this is what I was missing. Stream fusion does not use RULEs at all. (Except for the (stream . unstream = id) rule, which is needed only in the conversion to/from regular lists, which you probably aboie.)
But still, I think the key features of stream fusion and foldr/build fusion are the same: we must do enough inlining. INLINE pragmas may help; but join points are a problem because they are introduced by the compiler.
Your plugin uses a criterion like "if the function consumes or returns a fusible type, inline it", although I'm terribly hazy about the precise specification.
That same plugin might well be useful for other RULE-based libraries too. E.g. whether `map` returns explicit constructors (like (:) and []) or pseudo-constructors like (build g) doesn't matter. What matters is that the function is inlined.
Two other thoughts
First: inlining join points aggressively can cause exponential code blow-up. Consider
join j1 x = blah
join j2 x = case x of { Left x1 -> j1 x1; Right x2 -> j1 (x2+1) }
join j3 x = case x of { Left x1 -> j2 x1; Right x2 -> j2 (x2+1) }
join j4 x = case x of { Left x1 -> j3 x1; Right x2 -> j3 (x2+1) }
in ...
The types aren't right here but you'll get the idea. If you inline all the join points, you unravel a DAG into a tree of exponential size.
I'm not sure how you guard against that.
Second. Inlining join points may not be necessary to achieve fusion. Section 5 of "
Compiling without continuations" gives the idea. It might be worth understanding carefully why this doesn't work in your application.
Third:
If someone does write this code, in the case of stream fusion
both f and g will get inlined and fuse with "ys", so fusion is not an
issue. However, "ys" gets duplicated
In the example ys = h x
So are you saying that (h x) is computed twice? That would cause a perhaps-asymptotic increase in compile time! Is that what you get? You could say "don't do that" but it's hard to be completely sure you haven't.
Simon