I found iteratees to be the best of all worlds: you get the performance advantages of continuation-passing style, but you can still extract the start, middle, or end of a stream pipeline as an ordinary value that makes sense to reason about and test.