I\'m doing a bit of self study on functional languages (currently using Haskell). I came across a Haskell based assignment which requires defining map and filter in terms of
I am new to Haskell (in fact I've found this page asking the same question) but this is my understanding of lists and foldr so far:
(:)
operator. they terminate with the empty list []
. (think of it as a binary operator just like addition (+)
1+2+3+4 = 10
, 1:2:3:4:[] = [1,2,3,4]
[]
. if you link an empty list to any list the result is the list itself. so for a sum
function it is 0
. for a multiply function it is 1
, etc.So my solution is as follows:
filter' p = foldr (\x n -> if p x then x : n else n) []
the lambda expression is our link function, which will be used instead of the cons (:)
operator. Empty list is our default value for an empty list. If predicate is satisfied we link to the next item using (:)
as normal, else we simply don't link at all.
map' f = foldr (\x n -> f x : n) []
here we link f x
to the next item instead of just x
, which would simply duplicate the list.
Also, note that you don't need to use pattern matching, since we already tell foldr what to do in case of an empty list.
I know this question is really old but I just wanted to answer it anyway. I hope it is not against the rules.
In your definitions, you are doing pattern matching for x:xs
, which means, when your argument is [1,2,3,4]
, x
is bound to 1
and xs
is bound to the rest of the list: [2,3,4]
.
What you should not do is simply throw away x:
part. Then your foldr
will be working on whole list.
So your definitions should look as follows:
map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f xs = foldr (\x xs -> (f x):xs) [] xs
and
filter' :: (a -> Bool) -> [a] -> [a]
filter' p [] = []
filter' p xs = foldr (\x xs -> if p x then x:xs else xs ) [] xs