foldr (\x ante->[x]:[ante]) [4] [1,2,3]
So if I get foldr right, the first time the function (\x ante->[x]:[ante]) will do something, I will call this function f, it will be in:
f 3 [4] = [3]:[[4]] = [[3],[4]]
Why doesn't the function do this? It shows this error instead:
* Occurs check: cannot construct the infinite type: a ~ [a]
Expected type: [a]
Actual type: [[a]]
* In the expression: [x] : [ante]
In the first argument of `foldr', namely
`(\ x ante -> [x] : [ante])'
In the expression: foldr (\ x ante -> [x] : [ante]) [4] [1, 2, 3]
* Relevant bindings include
ante :: [a] (bound at testefoldr.hs:51:21)
x :: a (bound at testefoldr.hs:51:19)
folder4 :: [a] (bound at testefoldr.hs:51:1)
|51 | folder4 = foldr (\x ante->[x]:[ante]) [4] [1,2,3]
I created a .hs then I put
folder4 = foldr (\x ante->[x]:[ante]) [4] [1,2,3]
for faster testing. That's why there is folder4 in the error.
The foldr function has type:
foldr :: (a -> b -> b) -> b -> [a] -> b
So that means that it takes as input an element (type a) of the list to fold, together with the accumulator (type b), and returns an accumulator (again type b). In case Haskell was not statically typed, it would each time wrap the accumulator in a new list. So it would result in:
[4]
-> [[3],[4]]
-> [[2],[[3],[4]]]
-> [[1],[[2],[[3],[4]]]]
which makes no sense.
There are two problems here:
if ante has type b, then [x] : [ante] has type [b]; and
the type of the initial accumulator [4] is not the result of the foldr.
So you can fix this by writing:
foldr (\x ante->[x]:ante) [[4]] [1,2,3]
Let's pretend this type checks, and run it anyway
foldr (\x ante->[x]:[ante]) [4] [1,2,3]
Let's write f for \x ante -> [x]:[ante].
foldr f [4] [1,2,3]
=
f 1 (f 2 (f 3 [4]))
=
f 1 (f 2 ([3]:[[4]]))
=
f 1 (f 2 [[3],[4]])
So far, so good.
=
f 1 ([2] : [[[3],[4]]])
=
f 1 [[2] , [[3],[4]] ]
Now we're in trouble. Is that a [[Int]] or a [[[Int]]]?
Things get even worse if we continue.
The problem is that f must return a value of the same type as that of its second argument. Otherwise, we can't compose f in the way foldr does. Your f does not do that, instead adding a [] to the type at every call.
Related
I'm trying to see the difference in these 2 functions:
dupli = foldl (\acc x -> acc ++ [x,x]) []
dupli = foldr (\ x xs -> x : x : xs) []
I know the difference between foldl and foldr but for the examples I've seen on how it works, using (+), it looks the same except for the method of summing.
Why
dupli = foldr (\acc x -> acc ++ [x,x]) []
gives
/workspaces/hask_exercises/exercises/src/Lib.hs:142:27: error:
* Occurs check: cannot construct the infinite type: a ~ [a]
Expected type: [a]
Actual type: [[a]]
* In the expression: acc ++ [x, x]
In the first argument of `foldr', namely
`(\ acc x -> acc ++ [x, x])'
In the expression: foldr (\ acc x -> acc ++ [x, x]) []
* Relevant bindings include
x :: [a] (bound at src/Lib.hs:142:22)
acc :: [[a]] (bound at src/Lib.hs:142:18)
dupli' :: t [[a]] -> [a] (bound at src/Lib.hs:142:1)
|
142 | dupli' = foldr (\acc x -> acc ++ [x,x]) []
| ^^^^^^^^^^^^
exactly?
Look at the type signatures. (Note: I'm specializing both of these to [] rather than a general Foldable for simplicity here)
foldl :: (b -> a -> b) -> b -> [a] -> b
foldr :: (a -> b -> b) -> b -> [a] -> b
So in foldl, the "accumulator argument" is the first argument to the folding function, whereas in foldr, it's the second.
You mention (+). (+) is a function where the left-hand and right-hand arguments have the same type, so you wouldn't notice the difference. Specifically,
(+) :: Num a => a -> a -> a
But (:) is different.
(:) :: a -> [a] -> [a]
Since your initial accumulator is, in both cases, [], you can use (:) in the foldr case since the accumulator type [a] is the second argument, but in the foldl case we're required to do some tricks with ++.
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 []
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.
I did it like this – but it is not working:
ma f [] = []
ma f (xs) = foldl (\y ys -> ys++(f y)) [] xs
foldl :: (a -> b -> a) -> a -> [b] -> a
foldr :: (a -> b -> b) -> b -> [a] -> b
Why is there a difference in the function that fold takes. I mean, (a -> b -> a) and (a -> b -> b)?
Is it possible to define map using foldl?
I have another question
I have an expr.
map (:)
I want to know what it will do. I tried to test it but i only get error.
type is map (:) :: [a] -> [[a] -> [a]]
I tried to send in a list of [1,2,3]
Not if you want it to work for infinite as well as finite lists. head $ map id (cycle [1]) must return 1.
foldling over an infinite list diverges (never stops), because foldl is recursive. For example,
foldl g z [a,b,c] = g (g (g z a) b) c
Before g gets a chance to ignore its argument, foldl must reach the last element of the input list, to construct the first call to g. There is no last element in an infinite list.
As for your new question, here's a GHCi transcript that shows that map (:) is a function, and map (:) [1,2,3] is a list of functions, and GHCi just doesn't know how to Show functions:
Prelude> map (:)
<interactive>:1:0:
No instance for (Show ([a] -> [[a] -> [a]]))
Prelude> :t map (:)
map (:) :: [a] -> [[a] -> [a]]
Prelude> map (:) [1,2,3]
<interactive>:1:0:
No instance for (Show ([a] -> [a]))
Prelude> :t map (:) [1,2,3]
map (:) [1,2,3] :: (Num a) => [[a] -> [a]]
Prelude> map ($ [4]) $ map (:) [1,2,3]
[[1,4],[2,4],[3,4]]
Prelude> foldr ($) [4] $ map (:) [1,2,3]
[1,2,3,4]
It becomes more obvious when you swap the type-variable names in one of the functions:
foldl :: (b -> a -> b) -> b -> [a] -> b
foldr :: (a -> b -> b) -> b -> [a] -> b
...because after all, what we need is the result, i.e. [a] -> b. Or, more specially, [a] -> [b], so we might as well substitute that
foldl :: ([b] -> a -> [b]) -> [b] -> [a] -> [b]
foldr :: (a -> [b] -> [b]) -> [b] -> [a] -> [b]
which leaves only one non-list item in each signature, namely the a. That's what we can apply f to, so, in the case of foldl it has to be the 2nd argument of the lambda:
foldl (\ys y -> ys ++ f y)
As Xeo remarks, this isn't done yet, because f y has type b, not [b]. I think you can figure out how to fix that yourself...
ma f [] = []
ma f (xs) = foldl (\ys y -> ys++[(f y)]) [] xs
Works but why does order of arg to lambda matter.
ma f (xs) = foldl (\y ys -> ys++[(f y)]) [] xs gives error
i am trying to compute the harmonic series with the function below. But there's a type error and not quite sure what it mean? another question, why [5..1] would gives an empty list?
sumHR = foldr (+) 0 (\x -> map (1/) [1..x])
error message:
*** Expression : foldr (+) 0 (\x -> map (1 /) (enumFromTo x 1))
*** Term : \x -> map (1 /) (enumFromTo x 1)
*** Type : b -> [b]
*** Does not match : [a]
The error is telling you that your code is not well-typed and thus doesn't make sense.
Your function:
sumHR = foldr (+) 0 (\x -> map (1/) [1..x])
Consider:
Prelude> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
So for this to be true, (+) is the first argument and the types must unify (a -> b -> b and Num a => a -> a -> a unify to Num a => a -> a -> a).
The second argument is given type variable b, which we already know must be Num a => a. This is fine, you have provided 0 as the second argument.
The third argument must agree with the type Num a => [a]. However, you have provided a second argument that is a function:
Prelude> :t (\x -> map (1/) [1..x])
(\x -> map (1/) [1..x]) :: (Enum b, Fractional b) => b -> [b]
Unless you can show the compiler how a type of (Enum b, Fractional b) => b -> [b] can be made the same as Num a => [a] then you are stuck.
You might have ment a function such as:
sumHR x = foldr (+) 0 (map (1/) [1..x])
Were you trying to write it point-free? If so, you need to use the composition operator . to compose foldr (+) 0 with (\x -> map (1/) [1..x]).
sumHR = foldr (+) 0 . (\x -> map (1/) [1..x])
or, point-fully:
sumHR x = foldr (+) 0 (map (1/) [1..x])
(By the way, for efficiency you'll want to use foldl' instead of foldr)
The previous answers have explained how to fix the function with the signature you apparently want; however this isn't really a good way to compute a sequence since for each element you request it will have to start from the beginning. A far more efficient, an in Haskell actually easier, approach is to calculate one lazy list that represents the entire sequence. So, you start with
map (1/) [1..]
(or, perhaps more readable, [ 1/i | i<-[1..] ]), then perform "each element of the result is the sum of all preceding elements in the given list". This is called a scan. Since that is always strict in one entire side of the list (rather than just two elements, like a fold) it needs to be done from the left. You can write
sumHR' :: Fractional x => [x]
sumHR' = scanl (+) 0 [ 1/i | i<-[1..] ]
or, equivalently since the infinite list is never empty,
sumHR' = scanl1 (+) [ 1/i | i<-[1..] ]