Creating a safe version of Haskell 'init' function - haskell

I'm working my way through "Real World Haskell," and the assignment is to make safe versions of head, tail, last, and init. I've succeeded on the first three, but the Maybe typeclass is killing me on init.
Here is my code:
-- safeInit
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit (x:xs) = if null xs
then Just [x]
else x : (safeInit xs)
And here are the resultant errors on loading into GHCI (the function starts on line 23 of the original file:
[1 of 1] Compiling Main ( ch04.exercises.hs, interpreted )
> ch04.exercises.hs:27:26: error:
> • Couldn't match expected type ‘Maybe [a]’ with actual type ‘[a]’
> • In the expression: x : (safeInit xs)
> In the expression: if null xs then Just [x] else x : (safeInit xs)
> In an equation for ‘safeInit’:
> safeInit (x : xs) = if null xs then Just [x] else x : (safeInit xs)
> • Relevant bindings include
> xs :: [a] (bound at ch04.exercises.hs:25:13)
> x :: a (bound at ch04.exercises.hs:25:11)
> safeInit :: [a] -> Maybe [a] (bound at ch04.exercises.hs:24:1) | 27 | else x : (safeInit xs) |
> ^^^^^^^^^^^^^^^^^
>
> ch04.exercises.hs:27:31: error:
> • Couldn't match expected type ‘[a]’ with actual type ‘Maybe [a]’
> • In the second argument of ‘(:)’, namely ‘(safeInit xs)’
> In the expression: x : (safeInit xs)
> In the expression: if null xs then Just [x] else x : (safeInit xs)
> • Relevant bindings include
> xs :: [a] (bound at ch04.exercises.hs:25:13)
> x :: a (bound at ch04.exercises.hs:25:11)
> safeInit :: [a] -> Maybe [a] (bound at ch04.exercises.hs:24:1) | 27 | else x : (safeInit xs) |
> ^^^^^^^^^^^ Failed, no modules loaded.
Any way I mark or don't mark either the x or xs on the last two lines with Just, I get different, but very much related, typing errors. What subtlety on using the Maybe type with lists am I missing?

The main reason why this does not work is because your expression x : safeInit xs will not typecheck. Indeed, safeInit xs is a Maybe [a], but (:) has type (:) :: a -> [a] -> [a], so the types do not match.
There is also a semantical error. If null xs is True, then you should return Just [] instead of Just [x], since then x is the last element in the list.
You can make use of fmap :: Functor f => (a -> b) -> f a -> f b (so for f ~ Maybe, fmap is fmap :: (a -> b) -> Maybe a -> Maybe b), to alter a value that is wrapped in a Just:
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit [_] = Just []
safeInit (x:xs) = fmap (x:) (safeInit xs)
but this will result in a lot of wrapping and unwrapping of values in a Just. It also means that for an infinite list, it will get stuck in an infinite loop. We can simply check if the list contains at least on element, and then perform the init logic as the result of a function we wrap in a Just:
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit (x:xs) = Just (go xs x)
where go [] _ = []
go (x2:xs) x = x : go xs x2

One interesting problem is how to write safeInit in terms of foldr. Aside from the fun of the puzzle, this allows it to participate in the list fusion optimization in GHC as a "good consumer", which can improve performance in some cases. We start with the first (naive) version in Willem Van Onsem's answer:
safeInit0 :: [a] -> Maybe [a]
safeInit0 [] = Nothing
safeInit0 [_] = Just []
safeInit0 (x:xs) = fmap (x:) (safeInit0 xs)
The first problem with this is that it's not shaped quite like a fold: it has separate cases for [p] and for p:q:rs. A classic trick for patching this up is to pass a Maybe carrying the previous value in the list.
safeInit1 :: [a] -> Maybe [a]
safeInit1 xs0 = go xs0 Nothing
where
-- This first case only happens when
-- the whole list is empty.
go [] Nothing = Nothing
go [] (Just x) = Just [x]
go (x:xs) Nothing = go xs (Just x)
go (x:xs) (Just prev) = (prev:) <$> go xs (Just x)
The next problem is semantic: it doesn't work right with infinite or partially defined arguments. We want
safeInit [1..] = Just [1..]
but safeInit1 will diverge in this case, because fmap is necessarily strict in its Maybe argument. But it turns out there's a bit of information we can use: fmap will only be applied to a Just value in this case. Exercise: prove that.
We'll take advantage of that by representing Maybe [a] in a weird way as (Bool, [a]), where Nothing is represented as (False, []) and Just xs is represented as (True, xs). Now we can be lazier:
safeInit2 :: [a] -> Maybe [a]
safeInit2 xs = case helper2 xs of
(False, _) -> Nothing
(True, xs) -> Just xs
helper2 :: [a] -> (Bool, [a])
helper2 xs0 = go xs0 Nothing
where
go [] Nothing = (False, [])
go [] _ = (True, [])
go (x:xs) mb = case mb of
Nothing -> (True, rest)
Just p -> (True, p:rest)
where
rest = snd (go xs (Just x))
Now this has precisely the shape of a fold:
safeInit3 :: [a] -> Maybe [a]
safeInit3 xs = case helper3 xs of
(False, _) -> Nothing
(True, xs) -> Just xs
helper3 :: [a] -> (Bool, [a])
helper3 xs0 = foldr go stop x0 Nothing
where
stop Nothing = (False, [])
stop _ = (True, [])
go x r mb = case mb of
Nothing -> (True, rest)
Just p -> (True, p:rest)
where
rest = snd (r (Just x))
You might worry that all these intermediate Maybes and pairs will cause performance problems, but in fact GHC is able to optimize them all away, producing something very much like Willem Van Onsem's optimized implementation.

Related

Remove first element that fulfills predicate (Haskell)

I want to make a function that removes the first element that fulfills the predicate given in the second argument. Something like this:
removeFirst "abab" (< 'b') = "bab"
removeFirst "abab" (== 'b') = "aab"
removeFirst "abab" (> 'b') = "abab"
removeFirst [1,2,3,4] even = [1,3,4]
I wanted to do it by recursively, and came up with this:
removeFirst :: [a] -> (a -> Bool) -> [a]
removeFirst [] _ = []
rremoveFirst (x:xs) p = if p x then x : removeFirst xs p else removeFirst xs p
(Inspired by this question)
But I get a type-error, like this:
Couldn't match type ‘a’ with ‘Bool’
Expected: [Bool]
Actual: [a]
‘a’ is a rigid type variable bound by
the type signature for:
removeFirst :: forall a. [a] -> (a -> Bool) -> [a]
or this:
ghci> removeFirst [1,2,3,4] even
<interactive>:25:1: error:
* Variable not in scope: removeFirst :: [a0] -> (a1 -> Bool) -> t
* Perhaps you meant `rem' (imported from Prelude)
I know this is a relatively simple thing to program, I am just not familiar enough with Haskell yet. How can I do this "Haskell-style" (in one line)?
Before doing it "in style", why not first simply do it, so it works. This is how we learn.
"Variable not in scope: removeFirst ..." simply means you haven't defined the function named removeFirst.
So it seems you first tried to define it (and the error you show does not go with the code you show), then you got errors so it didn't get defined, and then you tried calling it and got the error saying it's not defined yet, naturally.
So, save your program in a source file, then load that file in GHCi. Then if you get any errors please copy-paste the full code from your file into your question (do not re-type it by hand). Also please specify what is it you do when you get the error messages, precisely. And be sure to include the error messages in full by copy-pasting them as well.
Then the logic of your code can be addressed.
Since others have posted working code, here's how I'd code this as a one-liner of sorts:
remFirst :: [a] -> (a -> Bool) -> [a]
remFirst xs p = foldr g z xs xs
where
g x r ~(_:tl) -- "r" for recursive result
| p x -- we've found it, then
= tl -- just return the tail
| otherwise
= x : r tl -- keep x and continue
z _ = [] -- none were found
Shortened, it becomes
remFirst xs p =
foldr (\x r ~(_:tl) -> if p x then tl else x : r tl)
(const []) xs xs
Not one line, but it works.
removeFirst :: [a] -> (a -> Bool) -> [a]
removeFirst (x:xs) pred
| pred x = xs
| otherwise = x : removeFirst xs pred
For a one-liner, I imagine you'd want to use foldl to walk across the list from the left.
EDIT
This solution uses guards, it first checks to see if the first element of the list passed in satisfies the predicate, and if not, it prepends it to the list and recursively checks the tail of the passed in list.
Using manual recursion does not lead to a one-liner solution, so let's try using some pre-built recursion scheme from the library.
Function scanl :: (b -> a -> b) -> b -> [a] -> [b] looks handy. It produces a succession of states, one state per input item.
Testing under the ghci interpreter:
$ ghci
λ>
λ> p = (=='b')
λ>
λ> xs = "ababcdab"
λ> ss = tail $ scanl (\(s,n) x -> if (p x) then (x,n+1) else (x,n)) (undefined,0) xs
λ>
λ> ss
[('a',0),('b',1),('a',1),('b',2),('c',2),('d',2),('a',2),('b',3)]
λ>
At that point, it is easy to spot and get rid of the one unwanted element, thru some simple data massaging:
λ>
λ> filter (\(x,n) -> (n /= 1) || (not $ p x)) ss
[('a',0),('a',1),('b',2),('c',2),('d',2),('a',2),('b',3)]
λ>
λ> map fst $ filter (\(x,n) -> (n /= 1) || (not $ p x)) ss
"aabcdab"
λ>
Let's now write our removeFirst function. I take the liberty to have the predicate as leftmost argument; this is what all library functions do.
removeFirst :: (a -> Bool) -> [a] -> [a]
removeFirst p =
let
stepFn = \(s,n) x -> if (p x) then (x,n+1) else (x,n)
p2 = \(x,n) -> (n /= 1) || (not $ p x)
in
map fst . filter p2 . tail . scanl stepFn (undefined,0)
If required, this version can be changed into a one-liner solution, just by expanding the values of stepFn and p2 into the last line. Left as an exercise for the reader. It makes for a long line, so it is debatable whether that improves readability.
Addendum:
Another approach consists in trying to find a library function, similar to splitAt :: Int -> [a] -> ([a], [a]) but taking a predicate instead of the list position.
So we submit the (a -> Bool) -> [a] -> ([a],[a]) type signature into the Hoogle specialized search engine.
This readily finds the break library function. It is exactly what we require.
λ>
λ> break (=='b') "zqababcdefab"
("zqa","babcdefab")
λ>
So we can write our removeFirst function like this:
removeFirst :: (a -> Bool) -> [a] -> [a]
removeFirst p xs = let (ys,zs) = break p xs in ys ++ (tail zs)
The source code for break simply uses manual recursion.

How to find Maximum element in List with maybe output

This code works
max_elem :: (Ord a) => [a] -> a
max_elem [x] = x
max_elem [] = error "No elements"
max_elem (x:xs)
|x > max_elem xs = x
|otherwise = max_elem xs
I want to have it so it returns Nothing if their are no elements and Just x for the maximum element
I tried the following
max_elem :: (Ord a) => [a] -> Maybe a
max_elem [x] = Just x
max_elem [] = Nothing
max_elem (x:xs)
|x > max_elem xs = Just x
|otherwise = max_elem xs
I got the following error. Recommendations to fix this please.
• Couldn't match expected type ‘a’ with actual type ‘Maybe a’
‘a’ is a rigid type variable bound by
the type signature for:
max_elem :: forall a. Ord a => [a] -> Maybe a
at <interactive>:208:13
• In the second argument of ‘(>)’, namely ‘max_elem xs’
In the expression: x > max_elem xs
In a stmt of a pattern guard for
an equation for ‘max_elem’:
x > max_elem xs
• Relevant bindings include
xs :: [a] (bound at <interactive>:211:13)
x :: a (bound at <interactive>:211:11)
max_elem :: [a] -> Maybe a (bound at <interactive>:209:1)
You get your error because of this line: x > max_elem xs. max_elem xs has type Maybe a where a is an element of a list. It has type a. You can't compare values of different types. a and Maybe a are different types. See Haskell equality table:
https://htmlpreview.github.io/?https://github.com/quchen/articles/blob/master/haskell-equality-table.html
Replace == operator with > and you will get the same table.
You can solve problem in your code by replacing x > max_elem xs with Just x > max_elem xs. Does it make sense to you?
As you can see, Maybe a data type has Ord a => Ord (Maybe a) instance which is actually really handy! So you can implement your function in even more concise way to utilize this Ord instance:
max_elem :: Ord a => [a] -> Maybe a
max_elem = foldr max Nothing . map Just
Though, this probably won't be the most efficient solution if you care about performance.
The error message was clear enough to solve your problem.
|x > max_elem xs = Just x
The problem is that you compare x which is a with max_elem which is Maybe a. That's why you got such error message. You can solve the problem with this code below.
max_elem :: (Ord a) => [a] -> Maybe a
max_elem [] = Nothing
max_elem (x:xs) = case (max_elem xs) of
Nothing -> Just x
Just y -> if x > y then Just x else Just y
We can generalize this task and work with all Foldables. Here we thus use the foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b function that folds a certain Foldable structure. We can do this with the function max . Just, and as initial element Nothing:
max_elem :: (Ord a, Foldable f) => f a -> Maybe a
max_elem = foldr (max . Just) Nothing
Note that this works since Haskell defines Maybe a to be an instance of Ord, given a is an instance of Ord, and it implements it in a way that Nothing is smaller than any Just element.
This makes the above definition perhaps a bit "unsafe" (in the sense that we here rely on the fact that from the moment we have a Just x, the max will select such Just x over a Nothing). When we would use min, this would not work (not without using some tricks).
We can also use pattern guards and thus solve the case where the list is empty in a different way, like:
max_elem :: Ord a => [a] -> Maybe a
max_elem [] = Nothing
max_elem l = Just (maximum l)
The problem is x > max_elem xs; max_elem xs is Maybe a, not a, meaning that it might return Nothing. However, you do know that it will only return Nothing if xs is empty, but you know xs won't be empty because you matched the case where it would using [x]. You can take advantage of this fact by writing a "non-empty" maximum:
max_elem_ne :: Ord a => a -> [a] -> a
max_elem_ne m [] = m
max_elem_ne m (x:xs)
| m > x = max_elem m xs
| otherwise = max_elem x xs
Or, alternatively, using max:
max_elem_ne :: Ord a => a -> [a] -> a
max_elem_ne m [] = m
max_elem_ne m (x:xs) = max_elem (max m x) xs
You can think of the first argument as the maximum value seen "so far", and the second list argument as the list of other candidates.
In this last form, you might have noticed that max_elem_ne is actually a just left fold, so you could even just write:
max_elem_ne :: Ord a => a -> [a] -> a
max_elem_ne = foldl' max
Now, with max_elem_ne, you can write your original max_elem:
Then you can write:
max_elem :: Ord a => [a] -> Maybe a
max_elem [] = Nothing
max_elem (x:xs) = Just (max_elem_ne x xs)
So you don't have to do any extraneous checks (like you would if you redundantly pattern matched on results), and the whole thing is type-safe.
You can also use the uncons :: [a] -> Maybe (a,[a]) utility function with fmap and uncurry to write:
max_elem :: Ord a => [a] -> Maybe a
max_elem = fmap (uncurry max_elem_ne) . uncons

How to pattern match the end of a list?

Say I wanted to remove all zeros at the end of a list:
removeEndingZeros :: (Num a, Eq a) => [a] -> [a]
removeEndingZeros (xs ++ [0]) = removeEndingZeros xs
removeEndingZeros xs = xs
This does not work because of the (++) operator in the argument. How can I determine the end of a list through pattern-matching?
There is a function in Data.List to do this:
dropWhileEnd :: (a -> Bool) -> [a] -> [a]
dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
So you can drop the trailing zeros with
dropWhileEnd (== 0)
Another, very similar, function can be implemented like this:
dropWhileEnd2 :: (a -> Bool) -> [a] -> [a]
dropWhileEnd2 p = foldr (\x xs -> if null xs && p x then [] else x : xs) []
dropWhileEnd2 p has exactly the same semantics as reverse . dropWhile p . reverse, but can reasonably be expected to be faster by a constant factor. dropWhileEnd has different, non-comparable strictness properties than the others (it's stricter in some ways and less strict in others).
Can you figure out circumstances under which each can be expected to be faster?

Is there any function in Haskell that applies a two argument function to two lists, element by element?

I just wanted to multiply two lists element by element, so I'd pass (*) as the first argument to that function:
apply :: Num a => (a -> a -> a) -> [a] -> [a] -> [a]
apply f xs ys = [f (xs !! i) (ys !! i) | i <- [0..(length xs - 1)]]
I may be asking a silly question, but I actually googled a lot for it and just couldn't find. Thank you, guys!
> :t zipWith
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
> zipWith (*) [1,2,3] [4,5,6]
[4,10,18]
It's the eighth result provided by Hoogle when queried with your type
(a -> a -> a) -> [a] -> [a] -> [a]
Moreover, when you need to implement your own function, use list !! index only as a last resort, since it usually leads to a bad performance, having a cost of O(index). Similarly, length should be used only when necessary, since it needs to scan the whole list.
In the zipWith case, you can avoid both and proceed recursively in a natural way: it is roughly implemented as
zipWith _ [] _ = []
zipWith _ _ [] = []
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
Note that this will only recurse as much as needed to reach the end of the shortest list. The remaining part of the longer list will be discarded.

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