Thanks. That's interesting (but a little beyond me). Seems like he's assuming that values beyond his range are zero whereas I'm trying to use the values at the edges of the range.

Is there anything I can do before I understand comonads? ;-)

Michael

Dan Weston wrote:
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







--
Now Playing: http://www.youtube.com/watch?v=SsnDdq4V8zg

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to