
There's an interesting blog post by Dan Piponi on the subject: http://sigfpe.blogspot.com/2007/01/monads-hidden-behind-every-zipper.html Summary: "convolution is comonadic" Dan Michael Feathers wrote:
I'm working on something and it's looking rather ugly.. essentially, it it's an application of a low pass filer to a dataset.
type Dataset = [Double] type FilterWindow3 = (Double,Double,Double)
internalList :: [a] -> [a] internalList = tail . init
lowPass3 :: FilterWindow3 -> Double lowPass3 (i, j, k) = (i + 2 * j + k) / 4.0
filter3 :: (FilterWindow3 -> Double) -> Dataset -> Dataset filter3 f3 ds = [(f3 x) | x <- formWindows ds]
iterFilter :: (Dataset -> Dataset) -> Int -> Dataset -> Dataset iterFilter f n ds | n > 0 = iterFilter f (n - 1) (f ds) | otherwise = ds
smooth :: Int -> Dataset -> Dataset smooth = iterFilter $ filter3 lowPass3
formWindows :: Dataset -> [FilterWindow3] formWindows ds = internalList $ zip3 x y z where c0 = [head ds] cn = [last ds] x = ds ++ cn ++ cn y = c0 ++ ds ++ cn z = c0 ++ c0 ++ ds
The key idea is that I can take care of edge conditions with that last function. It lets me build a list of 3-tuples, each of which is reduced to a single point in the next rewrite of the dataset. I used zip3 to build up that list, and I take care to keep the lists the same length by duplicating the head and last elements as necessary. Has anyone done this sort of thing before?
Any and all style advice welcome.
Thanks,
Michael Feathers