Several times I’ve wanted to traverse a list and pick out elements that have some property which also relies on, say, the next element in the list. For a simple example I have some code which counts how many times a function f changes sign over a specified interval [a,b]. This is fairly obvious in an imperative language like C:
for(double x=a; x<=b; x+=(b-a)/n){
s*f(x)>0 ? : printf("%e %e\n",x, f(x)), s=sgn(f(x));
}
In Haskell my first instinct was to zip the list with its tail and then apply the filter and extract the elements with fst or whatever. But that seems clumsy and inefficient, so I shoehorned it into being a fold:
signChanges f a b n = tail $
foldl (\(x:xs) y -> if (f x*f y)<0 then y:x:xs else x:xs) [a] [a,a+(b-a)/n..b]
Either way I feel there is a “right” way to do this (as there so often is in Haskell) and that I don’t know (or just haven’t realised) what it is. Any help with how to express this in a more idiomatic or elegant way would be greatly appreciated, as would advice on how, in general, to find the “right” way to do things.
Here is a “version” using a paramorphism (not quite the same as the question – but it should illustrate a paramorphism usefully enough), first we need
paraas it is not in the standard libraries:Using a paramorphism is much like using a fold but as well as seeing the accumulator we can see the rest of input:
The nice thing about
paracompared to zipping against the tail is that we can peek as far as we want into the rest of input.