# Would it be a good or bad idea to make dropWhile try to fuse?

wren romano winterkoninkje at gmail.com
Fri Jul 25 21:00:35 UTC 2014

```On Fri, Jul 25, 2014 at 12:35 AM, David Feuer <david.feuer at gmail.com> wrote:
> This is generally awful, because it could copy a large portion of the
> list with no benefit.

This is a general example of why paramorphisms are more powerful than
catamorphisms. That is, we have the following two notions of
"folding", where I will uncurry things to make the pattern clearer:

cata :: (b, a -> b -> b) -> [a] -> b
cata (nil,cons) = go
where
go [] = nil
go (x:xs) = cons x (go xs)

para :: (b, a -> ([a],b) -> b) -> [a] -> b
para (nil,cons) = go
where
go [] = nil
go (x:xs) = cons x (xs, go xs)

That is, we pass the algebra both the recursive structure and the
result of the recursive call, instead of only passing the latter. In
terms of the definability of (mathematical) functions, cata and para
have the same power; however, in terms of algorithms, paramorphisms
are strictly more powerful. For example, for Peano-style natural
numbers with paramorphisms we can implement an O(1)-time predecessor
function; but with only catamorphisms the best we can do is O(n)-time.
Analogously for lists, paramorphisms give us an O(1)-time tail
function (with structure sharing), whereas catamorphisms only admit
O(n)-time (without structure sharing). The dropWhile function is a
generalization of tail, so it'll run into exactly the same problem.

The trick, of course, is getting fusion to work for build/para (or
dually: apo/destroy). The problem is para doesn't make linear use of
the recursive substructure, so it isn't as amenable to eliminating
intermediate structures. In fact, there's a lot of interesting room
for research here.

> Does anyone
> have any thoughts about whether this one is worth pursuing?

The fact that it can result in massive copying is disturbing. Before
adopting it in the core libraries you'd want to make sure you can
guide the rewrite rules so that this definition of dropWhile is only
ever used when it will be fused away. But, before taking the time to
figure out how to do that, you'll probably want to find a bunch of
examples in the wild so that you can quantify the benefits and compare
that to the expected development cost. For example, if you have a
program that makes extensive use of dropWhile, you could manually
inline the fusing version and see how it compares.

--
Live well,
~wren
```