views:

146

answers:

4

I'm trying to write a function that takes a predicate f and a list and returns a list consisting of all items that satisfy f with preserved order. The trick is to do this using only higher order functions (HoF), no recursion, no comprehensions, and of course no filter.

+3  A: 

I'd suggest you look at foldr.

sclv
+4  A: 

I think you can use map this way:

filter' :: (a -> Bool) -> [a] -> [a]
filter' p xs = concat (map (\x -> if (p x) then [x] else []) xs)

You see? Convert the list in a list of lists, where if the element you want doesn't pass p, it turns to an empty list

filter' (> 1) [1 , 2, 3 ] would be: concat [ [], [2], [3]] = [2,3]

In prelude there is concatMap that makes the code simplier :P

the code should look like:

filter' :: (a -> Bool) -> [a] -> [a]
filter' p xs = concatMap (\x -> if (p x) then [x] else []) xs

using foldr, as suggested by sclv, can be done with something like this:

filter'' :: (a -> Bool) -> [a] -> [a]
filter'' p xs = foldr (\x y -> if p x then (x:y) else y) [] xs
Marco
There are other ways of doing it, Im kinda noob with haskell :P
Marco
+1  A: 

Well, are ifs and empty list allowed?

filter = (\f -> (>>= (\x -> if (f x) then return x else [])))
kohomologie
This is exactly as my answer only that it uses list monad..Or is there any other difference?Also, it is very unclear and hard to read..
Marco
Well, if you change [] with mzero and import Control.Monad, you'll get a filter working in any monad, not just in List. It is not filterM, however.
kohomologie
+2  A: 

You can express filter in terms of foldr:

filter p = foldr (\x xs-> if p x then x:xs else xs) []
Martijn
Thank you this is exactly what I was looking for!
dpsthree