How would you define map and filter using foldr in Haskell?

后端 未结 8 2399
一个人的身影
一个人的身影 2020-12-05 14:58

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

相关标签:
8条回答
  • 2020-12-05 15:50

    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:

    • lists are elements that are linked to the next element with the cons (:) 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]
    • foldr function takes a function that takes two parameters. this will replace the cons operator, which will define how each item is linked to the next.
    • it also takes the terminal value for the operation, which can be tought as the initial value that will be assigned to the empty list. for cons it is empty list []. if you link an empty list to any list the result is the list itself. so for a sumfunction it is 0. for a multiply function it is 1, etc.
    • and it takes the list itself

    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.

    0 讨论(0)
  • 2020-12-05 15:51

    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
    
    0 讨论(0)
提交回复
热议问题