[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