Haskell-a function that applies a function on a list - haskell

I am trying to create a function that accepts a function as parameter, and applies that function on every pair of elements in a list. For example, if I call my function foldPairs, then I would use it as so:
foldPairs (+) [1..10]
[3,7,11,15,19]
I tried using foldl in my attempt...
foldPairs :: (a->a->a) -> [a] -> [a]
foldPairs func lis = foldl func lis
However this clearly does not work. I think I might have to use curried and uncurried but I am not quite sure how. Could someone help me out?

Assuming, that for an odd-numbered input list we just discard the last element, the following will do the required:
foldPairs :: (a->a->a) -> [a] -> [a]
foldPairs _ [] = []
foldPairs _ [_] = []
foldPairs f (x:y:xs) = f x y : foldPairs f xs

The solution I would go with is to turn [1..10] into [[1,2],[3,4],[5,6],[7,8],[9,10]], then filter out any lists of length 1, convert to tuples, then map your function:
chunks :: Int -> [a] -> [[a]]
chunks n = reverse . go []
where
go acc [] = acc
go acc xs =
let (h, t) = splitAt n xs
in go (h:acc) t
Then simply
foldpairs :: (a -> a -> b) -> [a] -> [b]
foldpairs f
= map (uncurry f)
. map (\[x, y] -> (x, y))
. filter ((== 2) . length)
. chunks 2

Related

Haskell multifilter

I want to filter a list by predicates curried from another list.
For instance:
multifilter :: (a -> a -> Bool) -> [a] -> [a] -> [a]
multifilter _ _ [] = []
multifilter _ [] _ = []
multifilter f (x:xs) ys = (filter (f x) ys) ++ (multifilter f xs ys)
With usage such as:
prelude> multifilter (==) [1,2,3] [5,3,2]
[2,3]
Is there a standard way to do this?
You can use intersectBy:
λ> :t intersectBy
intersectBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]
λ> intersectBy (==) [1,2,3] [5,3,2]
[2,3]
You can use hoogle to search functions using type signature and finding them.
Note: This answer implements the specification expressed by the words and example in the question, rather than the different one given by the implementation of multifilter there. For the latter possibility, see gallais' answer.
Sibi's answer shows how you should actually do it. In any case, it is instructive to consider how you might write your function using filter. To begin with, we can establish two facts about it:
multifilter can be expressed directly as filter pred for some appropriate choice of pred. Given a fixed "predicate list", whether an element of the list you are multifiltering will be in the result only depends on the value of that element.
In multifilter f xs ys, the list you are filtering is xs, and the "predicate list" is ys. Were it not so, you would get [3,2] rather than [2,3] in your (quite well-chosen) example.
So we have:
multifilter :: (a -> a -> Bool) -> [a] -> [a] -> [a]
multifilter f xs ys = filter pred xs
where
pred = undefined -- TODO
All we need to do is implementing pred. Given an element x, pred should produce True if, for some element y of ys, f x y is true. We can conveniently express that using any:
pred x = any (\y -> f x y) ys
-- Or, with less line noise:
pred x = any (f x) ys
Therefore, multifilter becomes...
multifilter :: (a -> a -> Bool) -> [a] -> [a] -> [a]
multifilter f xs ys = filter pred xs
where
pred x = any (f x) ys
-- Or, more compactly:
multifilter :: (a -> a -> Bool) -> [a] -> [a] -> [a]
multifilter f xs ys = filter (\x -> any (f x) ys) xs
... which is essentially equivalent to intersectBy, as you can see by looking at intersectBy's implementation.
A third option is to use a list comprehension:
multifilter rel xs ys = [ x | x <- xs, y <- ys, x `rel` y ]
or, if you want partial application:
multifilter p xs ys = [ x | x <- xs, let f = p x, y <- ys, f y ]
If you want to use filter,
relate rel xs ys = filter (uncurry rel) $ liftM2 (,) xs ys
(and throw in map fst)
The answer you have accepted provides a function distinct from the one defined in your post: it retains elements from xs when yours retains elements from ys. You can spot this mistake by using a more general type for multifilter:
multifilter :: (a -> b -> Bool) -> [a] -> [b] -> [b]
Now, this can be implemented following the specification described in your post like so:
multifilter p xs ys = fmap snd
$ filter (uncurry p)
$ concatMap (\ x -> fmap (x,) ys) xs
If you don't mind retaining the values in the order they are in in ys then you can have an even simpler definition:
multifilter' :: (a -> b -> Bool) -> [a] -> [b] -> [b]
multifilter' p xs = filter (flip any xs . flip p)
Simply use Hoogle to find it out via the signature (a -> a -> Bool) -> [a] -> [a] -> [a]
https://www.haskell.org/hoogle/?hoogle=%28a+-%3E+a+-%3E+Bool%29+-%3E+%5Ba%5D+-%3E+%5Ba%5D+-%3E+%5Ba%5D
yields intersectBy:
intersectBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]

Haskell - replicate elements in a list

I want to write a Haskell program that replicates the elements of a list a given number of times.
Here's my code:
repli :: [a] -> a -> [a]
repli xs n = foldl1 (\x -> take n (repeat x)) xs
My problem is I get the following errors when compiling:
'take' is applied to too many arguments
couldn't match expected type '[a]->[a]' with actual type '[[a]]'
The type signature for foldl1 is:
foldl1 :: (a -> a -> a) -> [a] -> a
Hence, the first argument needs to be a function of two arguments. The lambda expression you're passing only takes one argument. You probably meant to do something like this:
repli :: [a] -> Int -> [a]
repli xs n = concat $ map (\x -> take n (repeat x)) xs
Or, to do it better, you can use the replicate function:
repli :: [a] -> Int -> [a]
repli xs n = concat $ map (replicate n) xs
Or, to do it even betterer, you can use the [] monad:
repli :: [a] -> Int -> [a]
repli xs n = xs >>= replicate n
How about this very simple line:
repli :: [a] -> Int -> [a]
repli xs n = concat (replicate n xs)
Consider Prelude replicate before rolling out your own function: http://zvon.org/other/haskell/Outputprelude/replicate_f.html
repli xs n = foldr (++) [] (replicate n xs)
you can use "take" and "repeat". You also need to provide a base case where the list is empty.
repli [] _ = []
repli (x:xs) y = take y (repeat x) ++ repli xs y
A simple solution that worked for me
f :: Int -> [Int] -> [Int]
f n arr = concatMap (\num -> replicate n num) arr

Can mapEvery be implemented with foldr

For a function that maps a function to every nth element in a list:
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f = zipWith ($) (drop 1 . cycle . take n $ f : repeat id)
Is it possible to implement this with foldr like ordinary map?
EDIT: In the title, changed 'folder' to 'foldr'. Autocorrect...
Here's one solution
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f as = foldr go (const []) as 1 where
go a as m
| m == n = f a : as 1
| otherwise = a : as (m+1)
This uses the "foldl as foldr" trick to pass state from the left to the right along the list as you fold. Essentially, if we read the type of foldr as (a -> r -> r) -> r -> [a] -> r then we instantiate r as Int -> [a] where the passed integer is the current number of elements we've passed without calling the function.
Yes, it can:
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f xs
= foldr (\y ys -> g y : ys) []
$ zip [1..] xs
where
g (i, y) = if i `mod` n == 0 then f y else y
And since it's possible to implement zip in terms of foldr, you could get even more fold-y if you really wanted. This even works on infinite lists:
> take 20 $ mapEvery 5 (+1) $ repeat 1
[1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2]
This is what it looks like with even more foldr and inlining g:
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery _ _ [] = []
mapEvery n f xs
= foldr (\(i, y) ys -> (if i `mod` n == 0 then f y else y) : ys) []
$ foldr step (const []) [1..] xs
where
step _ _ [] = []
step x zipsfn (y:ys) = (x, y) : zipsfn ys
Now, would I recommend writing it this way? Absolutely not. This is about as obfuscated as you can get while still writing "readable" code. But it does demonstrate that this is possible to use the very powerful foldr to implement relatively complex functions.

Adding predicate to a map function

Completely new to Haskell and learning through Learn Haskell the greater good.
I am looking at the map function
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
is it possible to add a predicate to this? for example, to only map to every other element in the list?
You can code your own version of map to apply f only to even (or odd) positions as follows. (Below indices start from 0)
mapEven :: (a->a) -> [a] -> [a]
mapEven f [] = []
mapEven f (x:xs) = f x : mapOdd f xs
mapOdd :: (a->a) -> [a] -> [a]
mapOdd f [] = []
mapOdd f (x:xs) = x : mapEven f xs
If instead you want to exploit the library functions, you can do something like
mapEven :: (a->a) -> [a] -> [a]
mapEven f = map (\(flag,x) -> if flag then f x else x) . zip (cycle [True,False])
or even
mapEven :: (a->a) -> [a] -> [a]
mapEven f = map (uncurry (\flag -> if flag then f else id)) . zip (cycle [True,False])
If you want to filter using an arbitrary predicate on the index, then:
mapPred :: (Int -> Bool) -> (a->a) -> [a] -> [a]
mapPred p f = map (\(i,x) -> if p i then f x else x) . zip [0..]
A more direct solution can be reached using zipWith (as #amalloy suggests).
mapEven :: (a->a) -> [a] -> [a]
mapEven f = zipWith (\flag x -> if flag then f x else x) (cycle [True,False])
This can be further refined as follows
mapEven :: (a->a) -> [a] -> [a]
mapEven f = zipWith ($) (cycle [f,id])
The "canonical" way to perform filtering based on positions is to zip the sequence with the naturals, so as to append an index to each element:
> zip [1, 1, 2, 3, 5, 8, 13] [0..]
[(1,0),(1,1),(2,2),(3,3),(5,4),(8,5),(13,6)]
This way you can filter the whole thing using the second part of the tuples, and then map a function which discards the indices:
indexedFilterMap p f xs = (map (\(x,_) -> f x)) . (filter (\(_,y) -> p y)) $ (zip xs [0..])
oddFibsPlusOne = indexedFilterMap odd (+1) [1, 1, 2, 3, 5, 8, 13]
To be specific to you question, one might simply put
mapEveryOther f = indexedFilterMap odd f
You can map with a function (a lambda is also possible):
plusIfOdd :: Int -> Int
plusIfOdd a
| odd a = a
| otherwise = a + 100
map plusIfOdd [1..5]
As a first step, write the function for what you want to do to the individual element of the list:
applytoOdd :: Integral a => (a -> a) -> a -> a
applytoOdd f x = if odd x
then (f x)
else x
So applytoOdd function will apply the function f to the element if the element is odd or else return the same element if it is even. Now you can apply map to that like this:
λ> let a = [1,2,3,4,5]
λ> map (applytoOdd (+ 100)) a
[101,2,103,4,105]
Or if you want to add 200 to it, then:
λ> map (applytoOdd (+ 200)) a
[201,2,203,4,205]
Looking on the comments, it seems you want to map based on the index position. You can modify your applytoOdd method appropriately for that:
applytoOdd :: Integral a => (b -> b) -> (a, b) -> b
applytoOdd f (x,y) = if odd x
then (f y)
else y
Here, the type variable a corresponds to the index element. If it's odd you are applying the function to the actual element of the list. And then in ghci:
λ> map (applytoOdd (+ 100)) (zip [1..5] [1..])
[101,2,103,4,105]
λ> map (applytoOdd (+ 200)) (zip [1..5] [1..])
[201,2,203,4,205]
Or use a list comprehension:
mapOdd f x = if odd x then f x else x
[ mapOdd (+100) x | x <- [1,2,3,4,5]]
I'm glad that you're taking the time to learn about Haskell. It's an amazing language. However it does require you to develop a certain mindset. So here's what I do when I face a problem in Haskell. Let's start with your problem statement:
Is it possible to add a predicate to the map function? For example, to only map to every other element in the list?
So you have two questions:
Is it possible to add a predicate to the map function?
How to map to every other element in the list?
So the way people think in Haskell is via type signatures. For example, when an engineer is designing a building she visualizes how the building should look for the top (top view), the front (front view) and the side (side view). Similarly when functional programmers write code they visualize their code in terms of type signatures.
Let's start with what we know (i.e. the type signature of the map function):
map :: (a -> b) -> [a] -> [b]
Now you want to add a predicate to the map function. A predicate is a function of the type a -> Bool. Hence a map function with a predicate will be of the type:
mapP :: (a -> Bool) -> (a -> b) -> [a] -> [b]
However, in your case, you also want to keep the unmapped values. For example mapP odd (+100) [1,2,3,4,5] should result in [101,2,103,4,105] and not [101,103,105]. Hence it follows that the type of the input list should match the type of the output list (i.e. a and b must be of the same type). Hence mapP should be of the type:
mapP :: (a -> Bool) -> (a -> a) -> [a] -> [a]
It's easy to implement a function like this:
map :: (a -> Bool) -> (a -> a) -> [a] -> [a]
mapP p f = map (\x -> if p x then f x else x)
Now to answer your second question (i.e. how to map to every other element in the list). You could use zip and unzip as follows:
snd . unzip . mapP (odd . fst) (fmap (+100)) $ zip [1..] [1,2,3,4,5]
Here's what's happening:
We first zip the index of each element with the element itself. Hence zip [1..] [1,2,3,4,5] results in [(1,1),(2,2),(3,3),(4,4),(5,5)] where the fst value of each pair is the index.
For every odd index element we apply the (+100) function to the element. Hence the resulting list is [(1,101),(2,2),(3,103),(4,4),(5,105)].
We unzip the list resulting in two separate lists ([1,2,3,4,5],[101,2,103,4,105]).
We discard the list of indices and keep the list of mapped results using snd.
We can make this function more general. The type signature of the resulting function would be:
mapI :: ((Int, a) -> Bool) -> (a -> a) -> [a] -> [a]
The definition of the mapI function is simple enough:
mapI :: ((Int, a) -> Bool) -> (a -> a) -> [a] -> [a]
mapI p f = snd . unzip . mapP p (fmap f) . zip [1..]
You can use it as follows:
mapI (odd . fst) (+100) [1,2,3,4,5]
Hope that helps.
Is it possible to add a predicate to this? for example, to only map to every other element in the list?
Yes, but functions should ideally do one relatively simple thing only. If you need to do something more complicated, ideally you should try doing it by composing two or more functions.
I'm not 100% sure I understand your question, so I'll show a few examples. First: if what you mean is that you only want to map in cases where a supplied predicate returns true of the input element, but otherwise just leave it alone, then you can do that by reusing the map function:
mapIfTrue :: (a -> Bool) -> (a -> a) -> [a] -> [a]
mapIfTrue pred f xs = map step xs
where step x | pred x = f x
| otherwise = x
If what you mean is that you want to discard list elements that don't satisfy the predicate, and apply the function to the remaining ones, then you can do that by combining map and filter:
filterMap :: (a -> Bool) -> (a -> b) -> [a] -> [b]
filterMap pred f xs = map f (filter pred xs)
Mapping the function over every other element of the list is different from these two, because it's not a predicate over the elements of the list; it's either a structural transformation of the list of a stateful traversal of it.
Also, I'm not clear whether you mean to discard or keep the elements you're not applying the function to, which would imply different answers. If you're discarding them, then you can do it by just discarding alternate list elements and then mapping the function over the remaining ones:
keepEven :: [a] -> [a]
keepEven xs = step True xs
where step _ [] = []
step True (x:xs) = x : step False xs
step False (_:xs) = step True xs
mapEven :: (a -> b) -> [a] -> [b]
mapEven f xs = map f (keepEven xs)
If you're keeping them, one way you could do it is by tagging each list element with its position, filtering the list to keep only the ones in even positions, discard the tags and then map the function:
-- Note: I'm calling the first element of a list index 0, and thus even.
mapEven :: (a -> a) -> [a] -> [a]
mapEven f xs = map aux (filter evenIndex (zip [0..] xs))
where evenIndex (i, _) = even i
aux (_, x) = f x
As another answer mentioned, zip :: [a] -> [b] -> [(a, b)] combines two lists pairwise by position.
But this is the general philosophy: to do a complex thing, use a combination of general-purpose generic functions. If you're familiar with Unix, it's similar to that.
Another simple way to write the last one. It's longer, but keep in mind that evens, odds and interleave all are generic and reusable:
evens, odds :: [a] -> [a]
evens = alternate True
odds = alternate False
alternate :: Bool -> [a] -> [a]
alternate _ [] = []
alternate True (x:xs) = x : alternate False xs
alternate False (_:xs) = alternate True xs
interleave :: [a] -> [a] -> [a]
interleave [] ys = ys
interleave (x:xs) ys = x : interleave ys xs
mapEven :: (a -> a) -> [a] -> [a]
mapEven f xs = interleave (map f (evens xs)) (odds xs)
You can't use a predicate because predicates operate on list values, not their indices.
I quite like this format for what you're trying to do, since it makes the case handling quite clear for the function:
newMap :: (t -> t) -> [t] -> [t]
newMap f [] = [] -- no items in list
newMap f [x] = [f x] -- one item in list
newMap f (x:y:xs) = (f x) : y : newMap f xs -- 2 or more items in list
For example, running:
newMap (\x -> x + 1) [1,2,3,4]
Yields:
[2,2,4,4]

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

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 foldr. For the life of me I'm not fully understanding how to go about this.
For example when I define a map function like:
map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f (x:xs) = foldr (\x xs -> (f x):xs) [] xs
I don't know why the first element of the list is always ignored. Meaning that:
map' (*2) [1,2,3,4]
results in [4,6,8] instead of [2,4,6,8]
Similarly, my filter' function:
filter' :: (a -> Bool) -> [a] -> [a]
filter' p [] = []
filter' p (x:xs) = foldr (\x xs -> if p x then x:xs else xs ) [] xs
when run as:
filter' even [2,3,4,5,6]
results in [4,6] instead of [2,4,6]
Why would this be the case? And how SHOULD I have defined these functions to get the expected results? I'm assuming something is wrong with my lambda expressions...
I wish I could just comment, but alas, I don't have enough karma.
The other answers are all good ones, but I think the biggest confusion seems to be stemming from your use of x and xs.
If you rewrote it as
map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f (x:xs) = foldr (\y ys -> (f y):ys) [] xs
you would clearly see that x is not even mentioned on the right-hand side, so there's no way that it could be in the solution.
Cheers
For your first question, foldr already has a case for the empty list, so you need not and should not provide a case for it in your own map.
map' f = foldr (\x xs -> f x : xs) []
The same holds for filter'
filter' p = foldr (\x xs -> if p x then x : xs else xs) []
Nothing is wrong with your lambda expressions, but there is something wrong with your definitions of filter' and map'. In the cons case (x:xs) you eat the head (x) away and then pass the tail to foldr. The foldr function can never see the first element you already ate. :)
Alse note that:
filter' p = foldr (\x xs -> if p x then x : xs else xs) []
is equivalent (η-equivalent) to:
filter' p xs = foldr (\x xs -> if p x then x : xs else xs) [] xs
I would define map using foldr and function composition as follows:
map :: (a -> b) -> [a] -> [b]
map f = foldr ((:).f) []
And for the case of filter:
filter :: (a -> Bool) -> [a] -> [a]
filter p = foldr (\x xs -> if p x then x:xs else xs) []
Note that it is not necessary to pass the list itself when defining functions over lists using foldr or foldl.
The problem with your solution is that you drop the head of the list and then apply the map over the list and
this is why the head of the list is missing when the result is shown.
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
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.
A different way to think about it - foldr exists because the following recursive pattern is used often:
-- Example 1: Sum up numbers
summa :: Num a => [a] -> a
summa [] = 0
summa (x:xs) = x + suma xs
Taking the product of numbers or even reversing a list looks structurally very similar to the previous recursive function:
-- Example 2: Reverse numbers
reverso :: [a] -> [a]
reverso [] = []
reverso (x:xs) = x `op` reverso xs
where
op = (\curr acc -> acc ++ [curr])
The structure in the above examples only differs in the initial value (0 for summa and [] for reverso) along with the operator between the first value and the recursive call (+ for summa and (\q qs -> qs ++ [q]) for reverso). So the function structure for the above examples can be generally seen as
-- Generic function structure
foo :: (a -> [a] -> [a]) -> [a] -> [a] -> [a]
foo op init_val [] = init_val
foo op init_val (x:xs) = x `op` foo op init_val xs
To see that this "generic" foo works, we could now rewrite reverso by using foo and passing it the operator, initial value, and the list itself:
-- Test: reverso using foo
foo (\curr acc -> acc ++ [curr]) [] [1,2,3,4]
Let's give foo a more generic type signature so that it works for other problems as well:
foo :: (a -> b -> b) -> b -> [a] -> b
Now, getting back to your question - we could write filter like so:
-- Example 3: filter
filtero :: (a -> Bool) -> [a] -> [a]
filtero p [] = []
filtero p (x:xs) = x `filterLogic` (filtero p xs)
where
filterLogic = (\curr acc -> if (p curr) then curr:acc else acc)
This again has a very similar structure to summa and reverso. Hence, we should be able to use foo to rewrite it. Let's say we want to filter the even numbers from the list [1,2,3,4]. Then again we pass foo the operator (in this case filterLogic), initial value, and the list itself. filterLogic in this example takes a p function, called a predicate, which we'll have to define for the call:
let p = even in foo (\curr acc -> if (p curr) then curr:acc else acc) [] [1,2,3,4]
foo in Haskell is called foldr. So, we've rewritten filter using foldr.
let p = even in foldr (\curr acc -> if (p curr) then curr:acc else acc) [] [1,2,3,4]
So, filter can be written with foldr as we've seen:
-- Solution 1: filter using foldr
filtero' :: (a -> Bool) -> [a] -> [a]
filtero' p xs = foldr (\curr acc -> if (p curr) then curr:acc else acc) [] xs
As for map, we could also write it as
-- Example 4: map
mapo :: (a -> b) -> [a] -> [b]
mapo f [] = []
mapo f (x:xs) = x `op` (mapo f xs)
where
op = (\curr acc -> (f curr) : acc)
which therefore can be rewritten using foldr. For example, to multiply every number in a list by two:
let f = (* 2) in foldr (\curr acc -> (f curr) : acc) [] [1,2,3,4]
So, map can be written with foldr as we've seen:
-- Solution 2: map using foldr
mapo' :: (a -> b) -> [a] -> [b]
mapo' f xs = foldr (\curr acc -> (f curr) : acc) [] xs
Your solution almost works .)
The problem is that you've got two differend bindings for x in both your functions (Inside the patternmatching and inside your lambda expression), therefore you loose track of the first Element.
map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f (x:xs) = foldr (\x xs -> (f x):xs) [] (x:xs)
filter' :: (a -> Bool) -> [a] -> [a]
filter' p [] = []
filter' p (x:xs) = foldr (\x xs -> if p x then x:xs else xs ) [] (x:xs)
This should to the trick :). Also: you can write your functions pointfree style easily.
*Main> :{
*Main| map' :: (a -> b) -> [a] -> [b]
*Main| map' = \f -> \ys -> (foldr (\x -> \acc -> f x:acc) [] ys)
*Main| :}
*Main> map' (^2) [1..10]
[1,4,9,16,25,36,49,64,81,100]
*Main> :{
*Main| filter' :: (a -> Bool) -> [a] -> [a]
*Main| filter' = \p -> \ys -> (foldr (\x -> \acc -> if p x then x:acc else acc) [] ys)
*Main| :}
*Main> filter' (>10) [1..100]
In the above snippets acc refers to accumulator and x refers to the last element.
Everything is correct in your lambda expressions. The problem is you are missing the first element in the list. If you try,
map' f (x:xs) = foldr (\x xs -> f x:xs) [] (x:xs)
then you shouldn't miss the first element anymore. The same logic applies to filter.
filter' p (x:xs) = foldr(\ y xs -> if p y then y:xs else xs) [] (x:xs)

Resources