[Haskell-cafe] Re: Sequence differences

Chad Scherrer chad.scherrer at pnl.gov
Fri Apr 10 12:04:38 EDT 2009


Joe Fredette <jfredett <at> gmail.com> writes:

> We can write your original function in another, cleaner way though, too, 
> since zip will "zip" to the smaller of the two lengths, so you don't 
> need to worry about doing the init and the tail, so `s` is really:
> 
> s _ []  = []
> s _ [x] = [x]
> s f ls  = [f a b | (a,b) <- zip ls (tail ls)]
> 
> but there is a function which does precisely what the third case does, 
> called "zipWith" which takes a
> binary function and two lists and -- well -- does what that list 
> comprehension does. In fact, it does
> what your whole function does... In fact, it _is_ your function, 
> specialized a little, eg:
> 
> yourZipWith f ls = zipWith f ls (tail ls)

A nice generalization of this that can be really useful is

movingWindow :: Int -> [a] -> [[a]]
movingWindow 1 xs = map (:[]) xs
movingWindow n xs = zipWith (:) xs . tail $ movingWindow (n-1) xs

So for example,

> movingWindow 3 [1..10]
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8],[7,8,9],[8,9,10]]

Then you can write

diff :: (Num a) => [a] -> [a]
diff = map (\[x,y] -> y - x) . movingWindow 2

Hopefully the intermediate lists are optimized away, but I haven't done any
performance testing.

Chad



More information about the Haskell-Cafe mailing list