Using Haskell's foldr - haskell

I'm learning Haskell and I've been wrestling with this problem:
Write func :: (a -> Bool) -> [a] -> [a] (take elements of a list until the predicate is false) using foldr
This is what I have so far:
func :: (a -> Bool) -> [a] -> [a]
func f li = foldr f True li
and got the following errors:
Couldn't match expected type ‘[a]’ with actual type ‘Bool’
and
Couldn't match type ‘Bool’ with ‘Bool -> Bool’
Expected type: a -> Bool -> Bool
Actual type: a -> Bool
I'm a bit confused since I learned foldr by passing a function with two arguments and getting a single value. For example I've used the function by calling
foldr (\x -> \y -> x*y*5) 1 [1,2,3,4,5]
to get a single value but not sure how it works when passing a single argument function into foldr and getting a list in return. Thank you very much.

Let’s do an easier case first, and write a function that uses foldr to do nothing (to break down the list and make a the same list). Let’s look at the type signature of foldr:
foldr :: (a -> b -> b) -> b -> [a] -> [b]
And we want to write an expression of the form
foldr ?1 ?2 :: [a] -> [a]
Now this tells us that (in the signature of foldr) we can replace b with [a].
A thing we haven’t worked out, ?2, is what we replace the end of the list with and it has type b = [a]. We don’t really have anything of type a so let’s just try the most stupid thing we can:
foldr ?1 []
And now the next missing thing: we have ?1 :: a -> [a] -> [a]. Let’s write a function for this. Now there are two reasonable things we can do with a list of things and another thing and nothing else:
Add it to the start
Add it to the end
I think 1 is more reasonable so let’s try that:
myFunc = foldr (\x xs -> x : xs) []
And now we can try it out:
> myFunc [1,2,3,4]
[1,2,3,4]
So what is the intuition for foldr here? Well one way to think of it is that the function passed gets put into your list instead of :, with the other item replacing [] so we get
foldr f x [1,2,3,4]
——>
foldr f x (1:(2:(3:(4:[]))))
——>
f 1 (f 2 (f 3 (f 4 x)))
So how can we do what we want (essentially implement takeWhile with foldr) by choosing our function carefully? Well there are two cases:
The predicate is true on the item being considered
The predicate is false for the item being considered
In case 1 we need to include our item in the list, and so we can try doing things like we did with our identity function above.
In case 2, we want to not include the item, and not include anything after it, so we can just return [].
Suppose our function does the right thing for the predicate "less than 3", here is how we might evaluate it:
f 1 (f 2 (f 3 (f 4 x)))
--T T F F (Result of predicate)
-- what f should become:
1 : (2 : ([] ))
——>
[1,2]
So all we need to do is implement f. Suppose the predicate is called p. Then:
f x xs = if p x then x : xs else []
And now we can write
func p = foldr f [] where
f x xs = if p x then x : xs else []

Related

Haskell- write map function using foldr

I am trying to write the map function using foldr. The problem is that when I ran this code :
> myMap f xs = foldr (\ acc x -> acc :(f x)) [] xs
I have the following problem:
No instance for (Num [a0]) arising from a use of 'it'
but when I run
myMap f xs = foldr (\x acc-> (f x):acc) [] xs
It works perfectly. Any ideas why?
the type of foldr is
foldr :: (a -> b -> b) -> b -> [a] -> b
therefore the binary operation that foldr uses to traverse and accumulate the list
has type (a -> b -> b),it first take an element of the list (type a)then the accumulator (type b) resulting in an expression of type b.
So, your first myMap function does not work becuase you are using "acc" and "x" in reverse order.
You want to apply f to x then append it to the acummulator of type b ( a list in this case)
The error you posted is not coming from your definition of myMap, it's coming from how you're using it. The type of the first myMap is ([a] -> [a]) -> [a] -> [a], which does not match the type of Prelude.map. In the second one you've swapped your variable names and also which one you're applying f to. The compiler doesn't care what you name the arguments in your lambda being passed to foldr, so foldr (\x acc -> f x : acc) is identical to foldr (\foo bar -> f foo : bar). That may be what's tripping you up here.
The second one works because (to put it simply) it's correct. In the first you're applying f to your accumulator list x (even though you have a variable named acc it's not your accumulator), so f must take a list and return a list. In the second you're applying f to each element, then prepending that to your accumulator list. If you had myMap (+1), it would have the type
myMap (+1) :: Num [a] => [a] -> [a]
Which says that you must pass it a list of values [a] where [a] implements Num, and currently there is no instance for Num [a], nor will there ever be.
TL;DR: In the first one you're applying your mapped function to your accumulator list, in the second one you're applying the mapped function to each element.

Does haskell's foldr always take a two-parameter lambda?

Haskell newb here
I'm working on this problem in haskell:
(**) Eliminate consecutive duplicates of list elements.
If a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed.
Example:
* (compress '(a a a a b c c a a d e e e e))
(A B C A D E)
The solution (which I had to look up) uses foldr:
compress' :: (Eq a) => [a] -> [a]
compress' xs = foldr (\x acc -> if x == (head acc) then acc else x:acc) [last xs] xs
This foldr, according to the solution, takes two parameters, x and acc. It would seem like all foldr's take these parameters; is there any exception to this? Like a foldr that takes 3 or more? If not, is this convention redundant and can the formula be written with less code?
foldr takes a function of 2 arguments, but this doesn't prevent it from taking a function of 3 arguments provided that function has the right type signature.
If we had a function
g :: x -> y -> z -> w
With
foldr :: (a -> b -> b) -> b -> [a] -> b
Where we want to pass g to foldr, then (a -> b -> b) ~ (x -> y -> z -> w) (where ~ is type equality). Since -> is right associative, this means we can write g's signature as
x -> y -> (z -> w)
and its meaning is the same. Now we've produced a function of two parameters that returns a function of one parameter. In order to unify this with the type a -> b -> b, we just need to line up the arguments:
a -> | x ->
b -> | y ->
b | (z -> w)
This means that b ~ z -> w, so y ~ b ~ z -> w and a ~ x so g's type really has to be
g :: x -> (z -> w) -> (z -> w)
implying
foldr g :: (z -> w) -> [x] -> (z -> w)
This is certainly not impossible, although more unlikely. Our accumulator is a function instead, and to me this begs to be demonstrated with DiffLists:
type DiffList a = [a] -> [a]
append :: a -> DiffList a -> DiffList a
append x dl = \xs -> dl xs ++ [x]
reverse' :: [a] -> [a]
reverse' xs = foldr append (const []) xs $ []
Note that foldr append (const []) xs returns a function which we apply to [] to reverse a list. In this case we've given an alias to functions of the type [a] -> [a] called DiffList, but it's really no different than having written
append :: a -> ([a] -> [a]) -> [a] -> [a]
which is a function of 3 arguments.
As with all things in haskell have a look at the types of things to guide your way you can do this for any function in ghci.
Looking at this for foldr we see:
Prelude> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
This slightly abstract string can be written in english as:
foldr is a function that takes
1 ) a function with two parameters one of type a and one of type b and returns something of type b
2 ) A value of type b
3 ) A list of values of type a
And returns a value of type b
Where a and b are type variables (see here for a good tutorial on them) which can be filled in with any type you like.
It turns out that you can solve your compress problem using a foldr with a three-argument function.
compress :: Eq a => [a] -> [a]
compress [] = []
compress (z:zs) = z : foldr f (const []) zs z
where f x k w | x==w = k x
| otherwise = x : k x
Let's dissect that. First, we can improve readability by changing the last two lines to
where f x k = \w -> if x==w then k x else x : k x
This makes it evident that a ternary function is nothing but a binary function returning a unary function. The advantage of looking at it in this way is that foldr is best understood when passed a binary function. Indeed, we are passing a binary function, which just happens to return a function.
Let's focus on types now:
f :: a -> (a -> [a]) -> (a -> [a])
f x k
So, x::a is the element of the list we are folding on. Function k is the result of the fold on the list tail. The result of f x k is something having the same type as k.
\w -> if .... :: (a -> [a])
The overall idea behind this anonymous function is as follows. The parameter k plays the same role as acc in the OP code, except it is a function expecting the previous element w in the list before producing the accumulated compressed list.
Concretely, we use now k x when we used acc, passing on the current element to the next step, since by that time x will become the previous element w. At the top-level, we pass z to the function which is returned by foldr f (const []).
This compress variant is lazy, unlike the posted solution. In fact, the posted solution needs to scan the whole list before starting producing something: this is due to (\x acc -> ...) being strict in acc, and to the use of last xs. Instead, the above compress outputs list elements in a "streaming" fashion. Indeed, it works with infinite lists as well:
> take 10 $ compress [1..]
[1,2,3,4,5,6,7,8,9,10]
That being said, I think using a foldr here feels a bit weird: the code above is arguably less readable than the explicit recursion.

Confusion about right folds in Haskell

Just for Background I am a Haskell and FP Beginner, self-learning.
I was going through folds on Learn You a Haskell for great good.
In this I came across this function
map' :: (a -> b) -> [a] -> [b]
map' f xs = foldr (\x acc -> f x : acc) [] xs
Everything is good but as far as I understood the first parameter of the lambda x matches with [] and second acc matches with xs. Right? The confusion starts with the author saying that Then, we prepend it to the accumulator, which is was []. How is the second parameter acc matching with [] which is the first argument? Doesn't make sense.
But his implementation is working while mine (with [] and xs interchanged as parameters) is giving a big error
Practice.hs:88:41:
Couldn't match type `a' with `b'
`a' is a rigid type variable bound by
the type signature for map' :: (a -> b) -> [a] -> [b]
at Practice.hs:87:9
`b' is a rigid type variable bound by
the type signature for map' :: (a -> b) -> [a] -> [b]
at Practice.hs:87:9
Expected type: [b]
Actual type: [a]
In the second argument of `foldr', namely `xs'
In the expression: foldr (\ x acc -> f x : acc) xs []
In an equation for map':
map' f xs = foldr (\ x acc -> f x : acc) xs []
Failed, modules loaded: none.
What am I missing here? Does foldr use flip internally? Or did I just understood it all incorrectly?
The lambda is not applied to [] and xs. Instead it's the first argument to foldr. The second and third arguments to foldr are [] and xs respectively.
It helps to look at what the "symbolic" form of the fold functions looks like. If we have a list of arbitrary elements [b1, b2, b3, b4] and initial element a then:
foldr f a [b1, b2, b3, b4] = f b1 (f b2 (f b3 (f b4 a)))
Conversely the foldl would look like.
foldl f a [b1, b2, b3, b4] = f (f (f (f a b1) b2) b3) b4
This of course ignores the laziness component of the execution, but the general idea still holds.
In your function you fold a function of two arguments which pushes a an element transformed under f onto a cons list.
map' f xs = foldr (\x acc -> f x : acc) [] xs
Expanding this out where (xs=[x0,x1,...,xn]) like above yields:
map' f xs = (f x0 : (f x1 : (f x2 : ... (f xn : []))))
Where the ellipsis is just pseudocode for the all the elements in between. We see is just precisely the element wise map. Hope that helps build intuition.
Begin with the type of foldr, from Hoogle.
foldr :: (a -> b -> b) -> b -> [a] -> b
From this, it is apparent that the second argument of the lambda must match the second argument to foldr, i.e. acc matches [] and x is an element of xs, because the first argument of the lambda has type a, and the third argument of foldr has type [a].
Note that foldl and foldr have different signatures, and hence the arguments in the lambda are swapped.
Might be simplest to just look at the implementation of foldr:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr k z = go
where
go [] = z
go (y:ys) = y `k` go ys
Then take a simple example like:
foldr (+) 0 [0, 1, 2, 4]
And follow exactly what happens as it recurses and generates the "spine".
Image of a foldr spine:
I'd recommend tracing what happens using pen and paper.
Yet another explanation, using long variable names for effect:
map :: (a -> b) -> [a] -> [b]
map f = foldr step []
where
-- If you have an incomplete solution to your problem, and the first
-- element of the input list, what is the last step you need to finish?
step elem incompleteSolution = f elem : incompleteSolution
The neat thing about using functions like foldr is that when you write your step function, the second argument to step will be the correct result for a smaller version of your problem.
One useful way to think of it is to imagine that foldr has already solved nearly all of your problem, but it's still missing the last step. For example, if you're trying to solve map f (x:xs), picture that foldr has already computed the solution for map f xs. Using that incomplete solution, f and x, what is the final step you need to perform to arrive at the complete solution? Well, as the code snippet illustrates, you apply f to x, and put that in front of the incomplete solution, and you're done.
The magic of foldr is that once you've figured out what to write for step, and what to use for the [] base case, then you're done. Your step function doesn't concern itself with the input list—all it can see is one input list element and an incomplete solution.

Haskell error using foldr

I am new to haskell and trying out some exercises
I dont understand whats the error generated and why it is generated
split = foldr
(\x y -> y:x)
[[]]
the error on the interpretator is as below
Occurs check: cannot construct the infinite type: a0 = [a0]
In the first argument of `(:)', namely `y'
In the expression: y : x
In the first argument of `foldr', namely `(\ x y -> y : x)'
Failed, modules loaded: none.
anyone can help? Thanks in advance
Type of foldr is
foldr :: (a -> b -> b) -> b -> [a] -> b
so in split
split = foldr (\x y -> y:x) [[]]
y and y:x has to be of same type, which is not possible for any x and y as y:x will always be one step deeper in the list than y.
I think you wanted to do x:y?
Recall the type of foldr: (a -> b -> b) -> b -> [a] -> b. This says that foldr expects a function that combines an element of the list with a value of the final result type, producing a new value of the result type.
For the first argument, you've given foldr the function \x y -> y:x, where x will be the list elements and y the result of the next step to the right; and the result of applying this lambda should have the same type as y.
But the type of (:) is a -> [a] -> [a]--that is, it appends a single element to the head of a list. In the expression y:x, you're taking something of the "result" type and using it as an element of a list used as the result.
Because of that, GHC attempts to infer that the result type b is the same as the type [b], which is then of course the same as the type [[b]], and [[[b]]]... and so on. Thus it complains about an "infinite type".
The posts before me answer your question, but after your comment i can see that you want a function that splits your list by a predicate.
You can use groupWith::Ord b => (a -> b) -> [a] -> [[a]] from the module GHC.Exts and supply it with a function of type (a -> Bool) in your example:
groupWith even [1,2,3,4,5,6] yields [[1,3,5],[2,4,6]]
Also, something ugly but that achieves the type of "outing" you want is:
split::Eq a => (a -> Bool) -> [a] -> [[a]]
split f ls = (ls \\ rl):rl:[]
where rl = filter f ls
But this will always split the supplied list in just two lists because of the binary function you supply.

Haskell / Miranda: Find the type of the function

Brief: This is a past exam question from a Miranda exam but the syntax is very similar to Haskell.
Question: What is the type of the following expression and what does it do? (The definitions
of the functions length and swap are given below).
(foldr (+) 0) . (foldr ((:) . length . (swap (:) [] )) [])
length [] = 0
length (x:xs) = 1 + length xs
swap f x y = f y x
Note:
Please feel free to reply in haskell syntax - sorry about putting using the stars as polytypes but i didn't want to translate it incorrectly into haskell. Basically, if one variable has type * and the other has * it means they can be any type but they must both be the same type. If one has ** then it means that it can but does not need to have the same type as *. I think it corresponds to a,b,c etc in haskell usuage.
My working so far
From the definition of length you can see that it finds the length of a list of anything so this gives
length :: [*] -> num.
From the definition I think swap takes in a function and two parameters and produces the function with the two parameters swapped over, so this gives
swap :: (* -> ** -> ***) -> ** -> [*] -> ***
foldr takes a binary function (like plus) a starting value and list and folds the list from right to left using that function. This gives
foldr :: (* -> ** -> **) -> ** -> [*] -> **)
I know in function composition it is right associative so for example everything to the right of the first dot (.) needs to produce a list because it will be given as an argument to the first foldr.
The foldr function outputs a single value ( the result of folding up the list) so I know that the return type is going to be some sort of polytype and not a list of polytype.
My problem
I'm unsure where to go from here really. I can see that swap needs to take in another argument, so does this partial application imply that the whole thing is a function? I'm quite confused!
You've already got the answer, I'll just write down the derivation step by step so it's easy to see all at once:
xxf xs = foldr (+) 0 . foldr ((:) . length . flip (:) []) [] $ xs
= sum $ foldr ((:) . length . (: [])) [] xs
= sum $ foldr (\x -> (:) (length [x])) [] xs
= sum $ foldr (\x r -> length [x]:r) [] xs
= sum $ map (\x -> length [x] ) xs
= sum [length [x] | x <- xs]
= sum [ 1 | x <- xs]
-- = length xs
xxf :: (Num n) => [a] -> n
So that, in Miranda, xxf xs = #xs. I guess its type is :: [*] -> num in Miranda syntax.
Haskell's length is :: [a] -> Int, but as defined here, it is :: (Num n) => [a] -> n because it uses Num's (+) and two literals, 0 and 1.
If you're having trouble visualizing foldr, it is simply
foldr (+) 0 (a:(b:(c:(d:(e:(...:(z:[])...))))))
= a+(b+(c+(d+(e+(...+(z+ 0)...)))))
= sum [a, b, c, d, e, ..., z]
Let's go through this step-by-step.
The length function obviously has the type that you described; in Haskell it's Num n => [a] -> n. The equivalent Haskell function is length (It uses Int instead of any Num n).
The swap function takes a function to invoke and reverses its first two arguments. You didn't get the signature quite right; it's (a -> b -> c) -> b -> a -> c. The equivalent Haskell function is flip.
The foldr function has the type that you described; namely (a -> b -> b) -> b -> [a] -> b. The equivalent Haskell function is foldr.
Now, let's see what each sub expression in the main expression means.
The expression swap (:) [] takes the (:) function and swaps its arguments. The (:) function has type a -> [a] -> [a], so swapping it yields [a] -> a -> [a]; the whole expression thus has type a -> [a] because the swapped function is applied to []. What the resulting function does is that it constructs a list of one item given that item.
For simplicity, let's extract that part into a function:
singleton :: a -> [a]
singleton = swap (:) []
Now, the next expression is (:) . length . singleton. The (:) function still has type a -> [a] -> [a]; what the (.) function does is that it composes functions, so if you have a function foo :: a -> ... and a function bar :: b -> a, foo . bar will have type b -> .... The expression (:) . length thus has type Num n => [a] -> [n] -> [n] (Remember that length returns a Num), and the expression (:) . length . singleton has type Num => a -> [n] -> [n]. What the resulting expression does is kind of strange: given any value of type a and some list, it will ignore the a and prepend the number 1 to that list.
For simplicity, let's make a function out of that:
constPrependOne :: Num n => a -> [n] -> [n]
constPrependOne = (:) . length . singleton
You should already be familiar with foldr. It performs a right-fold over a list using a function. In this situation, it calls constPrependOne on each element, so the expression foldr constPrependOne [] just constructs a list of ones with equal length to the input list. So let's make a function out of that:
listOfOnesWithSameLength :: Num n => [a] -> [n]
listOfOnesWithSameLength = foldr constPrependOne []
If you have a list [2, 4, 7, 2, 5], you'll get [1, 1, 1, 1, 1] when applying listOfOnesWithSameLength.
Then, the foldr (+) 0 function is another right-fold. It is equivalent to the sum function in Haskell; it sums the elements of a list.
So, let's make a function:
sum :: Num n => [n] -> n
sum = foldr (+) 0
If you now compose the functions:
func = sum . listOfOnesWithSameLength
... you get the resulting expression. Given some list, it creates a list of equal length consisting of only ones, and then sums the elements of that list. It does in other words behave exactly like length, only using a much slower algorithm. So, the final function is:
inefficientLength :: Num n => [a] -> n
inefficientLength = sum . listOfOnesWithSameLength

Resources