Both exercises have a common pattern of "filter by a transformed list, then untransform the result". See
-- exercise 1 skips :: [a] -> [[a]] skips xs = map (\n -> skip n xs) [1..(length xs)] skip :: Integral n => n -> [a] -> [a] skip n xs = map snd $ filter (\x -> (fst x) `mod` n == 0) (zip [1..] xs) --exercise 2 isLocalMaximum :: Integral a => (a,a,a) -> Bool isLocalMaximum (a,b,c) = b > a && b > c sliding3 :: [a] -> [(a,a,a)] sliding3 xs@(a:b:c:_) = (a,b,c) : sliding3 (tail xs) sliding3 _ =  localMaxima :: Integral a => [a] -> [a] localMaxima xs = map proj2 $ filter isLocalMaximum (sliding3 xs) where proj2 (_,b,_) = b -- *Main> filter isLocalMaximum (sliding3 [1,5,2,6,3]) -- [(1,5,2),(2,6,3)]
My instincts say that I could implement both of these something like this:
localMaxima' :: Integral a => [a] -> [a] localMaxima' xs = filterBy isLocalMaximum sliding3 xs
if only I could implement filterBy
filterBy :: (b -> Bool) -> ([a] -> [b]) -> [a] -> [a] filterBy p f as = as' where indexedAs = zipWith (,) [0..] as indexedBs = zipWith (,) [0..] (f as) indexedBs' = filter p indexedBs -- doesn't typecheck; how can we teach p about the tuples? indexes = map fst indexedBs as' = map (\i -> snd (indexedAs !! i)) indexes
It's also slower than just writing out a fold. Is this all a bad idea? I've always considered
fold a low level recursion operator and always try to structure in terms of higher level
filter but maybe I am misunderstanding.
My Haskell level is: understand LYAH but not written much code.
This is a homework to CIS 194 (2013 version) (though I am not taking the class, I am working through the material on my own)