Haskell - Filtering Lists by Comparison
I need to filter a list with a mask in Haskell.
It applies the function to an element of the mask list and the corresponding element in the data list, and if the function returns true, the corresponding element in the data list is included in the returned list.
For example, suppose I want to filter out data items that are greater than the mask items:
filtermask (\m d -> d > m) [1, 5, 7] [5, 6, 7]→[5, 6]
Any possible solution to this problem would be fantastic. So far, I've only done
filtermask f m d = f m d
That returns TRUE
EDIT: Solution, thanks to help from Tikhon:
filtermask f   =  filtermask f (fm:rm) (fd:rd) |f fm fd = fd:filtermask f rm rd |otherwise = filtermask f rm rd
Fundamentally, what you want to do is first pair up each element of the mask with an element of the list. We can do this with zip, which gives us a list of pairs.
Now that we have a list of pairs, we want to filter this using the comparison function (>, or whatever). The > function has a type Ord o => o -> o -> Bool; we need to turn this into a function which accepts a tuple. Happily, we can do this with uncurry; uncurry (>) gives us a function of type Ord o => (o, o) -> Bool.
Since we already have a list of pairs, we can just use this function to filter it. Now we have a list of only the pairs we want to keep; we need to get a list of just the element. We can do this by mapping a projection function like fst over the list.
Putting it all together, we get:
filterMask :: (o -> o -> Bool) -> [o] -> [o] -> [o] filterMask fn mask list = map fst (filter (uncurry fn) (zip list mask))
There's just one more subtle trick: what happens if the mask is shorter than our input list? With this function, the rest of the input list will be thrown out. If this is not what you want, you will need to repeat the mask. We can do this with a neat function called cycle which repeats a list forever. So that version would be:
filterMask fn mask list = map fst (filter (uncurry fn) (zip list (cycle mask)))