Issues with foldl in ghci - haskell

Trying this in ghci:
foldl (:) [1] [2,3,4]
which gives the following error:
<interactive>:51:7: error:
• Couldn't match type ‘a’ with ‘[a]’
Expected: [a] -> [[a]] -> [a]
Actual: [a] -> [[a]] -> [[a]]
‘a’ is a rigid type variable bound by
the inferred type of it :: [a]
at <interactive>:51:1-21
• In the first argument of ‘foldl’, namely ‘(:)’
In the expression: foldl (:) [1] [2, 3, 4]
In an equation for ‘it’: it = foldl (:) [1] [2, 3, 4]
• Relevant bindings include it :: [a] (bound at <interactive>:51:1)
But the same thing works with foldr
foldr (:) [1] [2,3,4]
which outputs [2,3,4,1]
Shouldn't the foldl output (above) be [1,2,3,4]? As per my understanding, the only difference between foldl and foldr is where the accumulator is placed so I am not understanding this error.

The signatures of foldl and foldr` differ. Indeed:
foldl :: Foldable f => (b -> a -> b) -> b -> t a -> b
foldr :: Foldable f => (a -> b -> b) -> b -> t a -> b
Notice the different order of a and b in the "fold function" (first parameter).
This is likely to stress that foldl f z [x1, x2, …, xn] is defined as:
foldl f z [x1, x2, …, xn] = f (… (f (f z x1) x2) …) xn
whereas for foldr f z [x1, x2, …, xn], we get:
foldr f z [x1, x2, …, xn] = f x1 (f x2 (… (f xn z) …))
You thus can work with:
foldl (flip (:)) [1] [2,3,4]
But this will not give the same result, since we construct:
foldl (flip (:)) [1] [2,3,4] = 4 : (3 : (2 : [1]))
= [4, 3, 2, 1]

Related

Refactoring Haskell lambda functions

I have a lambda function ((:) . ((:) x)) that I am passing to foldr like so: foldr ((:) . ((:) x)) [] xs where xs is a 2d list. I would like to refactor to make it clearer (so I can better understand it). I imagine it would be done like so:
foldr (\ element acc -> (element:acc) . (x:acc)) [] xs
But this gives me the error:
ex.hs:20:84: error:
• Couldn't match expected type ‘a0 -> b0’ with actual type ‘[[a]]’
• Possible cause: ‘(:)’ is applied to too many arguments
In the second argument of ‘(.)’, namely ‘(x : acc)’
In the expression: (element : acc) . (x : acc)
In the first argument of ‘foldr’, namely
‘(\ element acc -> (element : acc) . (x : acc))’
• Relevant bindings include
acc :: [[a]] (bound at ex.hs:20:60)
element :: [a] (bound at ex.hs:20:52)
xs :: [[a]] (bound at ex.hs:20:30)
x :: [a] (bound at ex.hs:20:28)
prefixes :: [a] -> [[a]] (bound at ex.hs:20:1)
|
20 | prefixes = foldr (\x xs -> [x] : (foldr (\ element acc -> (element:acc) . (x:acc)) [] xs)) []
|
Edit: My all relevant code surrounding this snippet is
prefixes :: Num a => [a] -> [[a]]
prefixes = foldr (\x acc -> [x] : (foldr ((:) . ((:) x)) [] acc)) []
and its invocation is:
prefixes [1, 2, 3]
How can I refactor the lambda ((:) . ((:) x)) to include both its arguments?
You can step-by-step convert it to a lambda.
(:) . ((:) x)
\y -> ((:) . (((:) x)) y -- conversion to lambda
\y -> (:) (((:) x) y) -- definition of (.)
\y -> (:) (x : y) -- rewrite second (:) using infix notation
\y z -> (:) (x : y) z -- add another parameter
\y z -> (x : y) : z -- rewrite first (:) using infix notation

foldr and foldr1 Haskell

I am trying to dive deep in the folds, considering it seems a very powerful asset to me. However, can you help me with this:
foldr (/) 2 [1,2,3] -- (1/(2/(3/2))), result 0,75 {where 2 is base)
foldr1 (/) [2,2,3] -- (1/(2/(3/2))), result 3.00 {where 2 is base)
I think I am seriously overseeing an essential difference between the folds. Thx
foldr :: (a -> b -> b) -> b -> [a] -> b has as implementation:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr _ z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
So that means that if we enter foldr f z [x1, x2, x3], then it is evaluated as:
foldr f z [x1, x2, x3]
-> f x1 (foldr f z [x2, x3])
-> f x1 (f x2 (foldr f z [x3]))
-> f x1 (f x2 (f x3 (foldr f z [])))
-> f x1 (f x2 (f x3 z))
So for your example that will evaluate to:
(/) 1 ((/) 2 ((/) 3 2))
= 1 / (2 / (3 / 2))
= 1 / (2 / 1.5)
= 1 / 1.33333...
= 0.75
The foldr1 :: (a -> a -> a) -> [a] -> a function is almost similar, except that in case we see the a 1-element list, we return that element, so the difference is:
foldr1 :: (a -> a -> a) -> [a] -> a
foldr1 _ [x] = x
foldr f (x:xs) = f x (foldr1 f xs)
So that means that for a foldr1 f [x1, x2, x3] we get:
foldr1 f [x1, x2, x3]
-> f x1 (foldr1 f [x2, x3])
-> f x1 (f x2 (foldr1 f [x3]))
-> f x1 (f x2 x3))
So for the sample input, we get:
(/) 2 ((/) 2 3)
= 2 / (2 / 3)
= 2 / 0.6666...
= 3.0
So in case z and xi have the same type, then foldr f z [x1, ..., xn] is equal to foldr1 f [x1, ..., xn, z].
In general
foldr1 op [y1, ..., yn, x]
is essentially the same as
foldr op x [y1, ..., yn]
as long as n >= 1. That is, in your special case
foldr1 (/) [2, 2, 3]
will evaluate to 2/(2/3) = 3.
With the division operator, it's a bit boring, because
foldr1 (/) [y, y, x1, ... , xn]
= y/(y/(foldr1 (/) [x1, ..., xn]))
= foldr1 (/) [x1, ..., xn]
for all n >= 1. So, in your example, it should just return the result of
foldr1 (/) [3]
which is of course 3.0, and it does indeed evaluate to 3.0.
Here is less degenerate example:
foldr1 (/) [2, 3, 5, 7] -- evals to 0.47619047619047616
Here, it gives the same result as 2 / (3 / (5 / 7)), which is in turn
the same as
foldr (/) 7 [2, 3, 5]
I hope it clarifies the order of evaluation a little bit.

Why does foldr give me this error?

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.

Why can you reverse list with foldl, but not with foldr in Haskell

Why can you reverse a list with the foldl?
reverse' :: [a] -> [a]
reverse' xs = foldl (\acc x-> x : acc) [] xs
But this one gives me a compile error.
reverse' :: [a] -> [a]
reverse' xs = foldr (\acc x-> x : acc) [] xs
Error
Couldn't match expected type `a' with actual type `[a]'
`a' is a rigid type variable bound by
the type signature for reverse' :: [a] -> [a] at foldl.hs:33:13
Relevant bindings include
x :: [a] (bound at foldl.hs:34:27)
acc :: [a] (bound at foldl.hs:34:23)
xs :: [a] (bound at foldl.hs:34:10)
reverse' :: [a] -> [a] (bound at foldl.hs:34:1)
In the first argument of `(:)', namely `x'
In the expression: x : acc
Every foldl is a foldr.
Let's remember the definitions.
foldr :: (a -> s -> s) -> s -> [a] -> s
foldr f s [] = s
foldr f s (a : as) = f a (foldr f s as)
That's the standard issue one-step iterator for lists. I used to get my students to bang on the tables and chant "What do you do with the empty list? What do you do with a : as"? And that's how you figure out what s and f are, respectively.
If you think about what's happening, you see that foldr effectively computes a big composition of f a functions, then applies that composition to s.
foldr f s [1, 2, 3]
= f 1 . f 2 . f 3 . id $ s
Now, let's check out foldl
foldl :: (t -> a -> t) -> t -> [a] -> t
foldl g t [] = t
foldl g t (a : as) = foldl g (g t a) as
That's also a one-step iteration over a list, but with an accumulator which changes as we go. Let's move it last, so that everything to the left of the list argument stays the same.
flip . foldl :: (t -> a -> t) -> [a] -> t -> t
flip (foldl g) [] t = t
flip (foldl g) (a : as) t = flip (foldl g) as (g t a)
Now we can see the one-step iteration if we move the = one place leftward.
flip . foldl :: (t -> a -> t) -> [a] -> t -> t
flip (foldl g) [] = \ t -> t
flip (foldl g) (a : as) = \ t -> flip (foldl g) as (g t a)
In each case, we compute what we would do if we knew the accumulator, abstracted with \ t ->. For [], we would return t. For a : as, we would process the tail with g t a as the accumulator.
But now we can transform flip (foldl g) into a foldr. Abstract out the recursive call.
flip . foldl :: (t -> a -> t) -> [a] -> t -> t
flip (foldl g) [] = \ t -> t
flip (foldl g) (a : as) = \ t -> s (g t a)
where s = flip (foldl g) as
And now we're good to turn it into a foldr where type s is instantiated with t -> t.
flip . foldl :: (t -> a -> t) -> [a] -> t -> t
flip (foldl g) = foldr (\ a s -> \ t -> s (g t a)) (\ t -> t)
So s says "what as would do with the accumulator" and we give back \ t -> s (g t a) which is "what a : as does with the accumulator". Flip back.
foldl :: (t -> a -> t) -> t -> [a] -> t
foldl g = flip (foldr (\ a s -> \ t -> s (g t a)) (\ t -> t))
Eta-expand.
foldl :: (t -> a -> t) -> t -> [a] -> t
foldl g t as = flip (foldr (\ a s -> \ t -> s (g t a)) (\ t -> t)) t as
Reduce the flip.
foldl :: (t -> a -> t) -> t -> [a] -> t
foldl g t as = foldr (\ a s -> \ t -> s (g t a)) (\ t -> t) as t
So we compute "what we'd do if we knew the accumulator", and then we feed it the initial accumulator.
It's moderately instructive to golf that down a little. We can get rid of \ t ->.
foldl :: (t -> a -> t) -> t -> [a] -> t
foldl g t as = foldr (\ a s -> s . (`g` a)) id as t
Now let me reverse that composition using >>> from Control.Arrow.
foldl :: (t -> a -> t) -> t -> [a] -> t
foldl g t as = foldr (\ a s -> (`g` a) >>> s) id as t
That is, foldl computes a big reverse composition. So, for example, given [1,2,3], we get
foldr (\ a s -> (`g` a) >>> s) id [1,2,3] t
= ((`g` 1) >>> (`g` 2) >>> (`g` 3) >>> id) t
where the "pipeline" feeds its argument in from the left, so we get
((`g` 1) >>> (`g` 2) >>> (`g` 3) >>> id) t
= ((`g` 2) >>> (`g` 3) >>> id) (g t 1)
= ((`g` 3) >>> id) (g (g t 1) 2)
= id (g (g (g t 1) 2) 3)
= g (g (g t 1) 2) 3
and if you take g = flip (:) and t = [] you get
flip (:) (flip (:) (flip (:) [] 1) 2) 3
= flip (:) (flip (:) (1 : []) 2) 3
= flip (:) (2 : 1 : []) 3
= 3 : 2 : 1 : []
= [3, 2, 1]
That is,
reverse as = foldr (\ a s -> (a :) >>> s) id as []
by instantiating the general transformation of foldl to foldr.
For mathochists only. Do cabal install newtype and import Data.Monoid, Data.Foldable and Control.Newtype. Add the tragically missing instance:
instance Newtype (Dual o) o where
pack = Dual
unpack = getDual
Observe that, on the one hand, we can implement foldMap by foldr
foldMap :: Monoid x => (a -> x) -> [a] -> x
foldMap f = foldr (mappend . f) mempty
but also vice versa
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f = flip (ala' Endo foldMap f)
so that foldr accumulates in the monoid of composing endofunctions, but now to get foldl, we tell foldMap to work in the Dual monoid.
foldl :: (b -> a -> b) -> b -> [a] -> b
foldl g = flip (ala' Endo (ala' Dual foldMap) (flip g))
What is mappend for Dual (Endo b)? Modulo wrapping, it's exactly the reverse composition, >>>.
For a start, the type signatures don't line up:
foldl :: (o -> i -> o) -> o -> [i] -> o
foldr :: (i -> o -> o) -> o -> [i] -> o
So if you swap your argument names:
reverse' xs = foldr (\ x acc -> x : acc) [] xs
Now it compiles. It won't work, but it compiles now.
The thing is, foldl, works from left to right (i.e., backwards), whereas foldr works right to left (i.e., forwards). And that's kind of why foldl lets you reverse a list; it hands you stuff in reverse order.
Having said all that, you can do
reverse' xs = foldr (\ x acc -> acc ++ [x]) [] xs
It'll be really slow, however. (Quadratic complexity rather than linear complexity.)
You can use foldr to reverse a list efficiently (well, most of the time in GHC 7.9—it relies on some compiler optimizations), but it's a little weird:
reverse xs = foldr (\x k -> \acc -> k (x:acc)) id xs []
I wrote an explanation of how this works on the Haskell Wiki.
foldr basically deconstructs a list, in the canonical way: foldr f initial is the same as a function with patterns:(this is basically the definition of foldr)
ff [] = initial
ff (x:xs) = f x $ ff xs
i.e. it un-conses the elements one by one and feeds them to f. Well, if all f does is cons them back again, then you get the list you originally had! (Another way to say that: foldr (:) [] ≡ id.
foldl "deconstructs" the list in inverse order, so if you cons back the elements you get the reverse list. To achieve the same result with foldr, you need to append to the "wrong" end – either as MathematicalOrchid showed, inefficiently with ++, or by using a difference list:
reverse'' :: [a] -> [a]
reverse'' l = dl2list $ foldr (\x accDL -> accDL ++. (x:)) empty l
type DList a = [a]->[a]
(++.) :: DList a -> DList a -> DList a
(++.) = (.)
emptyDL :: DList a
emptyDL = id
dl2list :: DLList a -> [a]
dl2list = ($[])
Which can be compactly written as
reverse''' l = foldr (flip(.) . (:)) id l []
This is what foldl op acc does with a list with, say, 6 elements:
(((((acc `op` x1) `op` x2) `op` x3) `op` x4) `op` x5 ) `op` x6
while foldr op acc does this:
x1 `op` (x2 `op` (x3 `op` (x4 `op` (x5 `op` (x6 `op` acc)))))
When you look at this, it becomes clear that if you want foldl to reverse the list, op should be a "stick the right operand to the beginning of the left operand" operator. Which is just (:) with arguments reversed, i.e.
reverse' = foldl (flip (:)) []
(this is the same as your version but using built-in functions).
When you want foldr to reverse the list, you need a "stick the left operand to the end of the right operand" operator. I don't know of a built-in function that does that; if you want you can write it as flip (++) . return.
reverse'' = foldr (flip (++) . return) []
or if you prefer to write it yourself
reverse'' = foldr (\x acc -> acc ++ [x]) []
This would be slow though.
A slight but significant generalization of several of these answers is that you can implement foldl with foldr, which I think is a clearer way of explaining what's going on in them:
myMap :: (a -> b) -> [a] -> [b]
myMap f = foldr step []
where step a bs = f a : bs
-- To fold from the left, we:
--
-- 1. Map each list element to an *endomorphism* (a function from one
-- type to itself; in this case, the type is `b`);
--
-- 2. Take the "flipped" (left-to-right) composition of these
-- functions;
--
-- 3. Apply the resulting function to the `z` argument.
--
myfoldl :: (b -> a -> b) -> b -> [a] -> b
myfoldl f z as = foldr (flip (.)) id (toEndos f as) z
where
toEndos :: (b -> a -> b) -> [a] -> [b -> b]
toEndos f = myMap (flip f)
myReverse :: [a] -> [a]
myReverse = myfoldl (flip (:)) []
For more explanation of the ideas here, I'd recommend reading Tom Ellis' "What is foldr made of?" and Brent Yorgey's "foldr is made of monoids".

foldl . foldr function composition - Haskell

So, I'm really frying my brain trying do understand the foldl.foldr composition.
Here is a example:
(foldl.foldr) (+) 1 [[1,2,3],[4,5,6]]
The result is 22, but what's really happening here?
To me it looks like this is what is happening: foldl (+) 1 [6,15].
My doubt is related to the foldr part. Shouldn't it add the 1 to all the sub-lists? Like this: foldr (+) 1 [1,2,3].
In my head the 1 is added just one time, is it right? (probably not, but I want to know how/why!).
I'm very confused (and perhaps making all the confusion, haha).
Thank you!
(foldl.foldr) (+) 1 [[1,2,3],[4,5,6]]
becomes
foldl (foldr (+)) 1 [[1,2,3],[4,5,6]]
So you get
foldl (foldr (+)) (foldr (+) 1 [1,2,3]) [[4,5,6]]
after the first step of foldl, or
foldl (foldr (+)) 7 [[4,5,6]]
if we evaluate the applied foldr (unless the strictness analyser kicks in, it would in reality remain an unevaluated thunk until the foldl has traversed the entire list, but the next expression is more readable with it evaluated), and that becomes
foldl (foldr (+)) (foldr (+) 7 [4,5,6]) []
and finally
foldl (foldr (+)) 22 []
~> 22
Let's examine foldl . foldr. Their types are
foldl :: (a -> b -> a) -> (a -> [b] -> a)
foldr :: (c -> d -> d) -> (d -> [c] -> d)
I intentionally used distinct type variables and I added parentheses so that it becomes more apparent that we view them now as functions of one argument (and their results are functions). Looking at foldl we see that it is a kind of lifting function: Given a function that produces a from a using b, we lift it so that it works on [b] (by repeating the computation). Function foldr is similar, just with arguments reversed.
Now what happens if we apply foldl . foldr? First, let's derive the type: We have to unify the type variables so that the result of foldr matches the argument of foldl. So we have to substitute: a = d, b = [c]:
foldl :: (d -> [c] -> d) -> (d -> [[c]] -> d)
foldr :: (c -> d -> d) -> (d -> [c] -> d)
So we get
foldl . foldr :: (c -> d -> d) -> (d -> [[c]] -> d)
And what is its meaning? First, foldr lifts the argument of type c -> d -> d to work on lists, and reverses its arguments so that we get d -> [c] -> d. Next, foldl lifts this function again to work on [[c]] - lists of [c].
In your case, the operation being lifted (+) is associative, so we don't have care about the order of its application. The double lifting simply creates a function that applies the operation on all the nested elements.
If we use just foldl, the effect is even nicer: We can lift multiple times, like in
foldl . foldl . foldl . foldl
:: (a -> b -> a) -> (a -> [[[[b]]]] -> a)
Actually, (foldl.foldr) f z xs === foldr f z (concat $ reverse xs).
Even if f is an associative operation, the correct sequence of applications matters, as it can have an impact on performance.
We begin with
(foldl.foldr) f z xs
foldl (foldr f) z xs
writing with g = foldr f and [x1,x2,...,xn_1,xn] = xs for a moment, this is
(...((z `g` x1) `g` x2) ... `g` xn)
(`g` xn) ((`g` xn_1) ... ((`g` x1) z) ... )
foldr f z $ concat [xn,xn_1, ..., x1]
foldr f z $ concat $ reverse xs
So in your case the correct reduction sequence is
(foldl.foldr) 1 [[1,2,3],[4,5,6]]
4+(5+(6+( 1+(2+(3+ 1)))))
22
To wit,
Prelude> (foldl.foldr) (:) [] [[1..3],[4..6],[7..8]]
[7,8,4,5,6,1,2,3]
Similarly, (foldl.foldl) f z xs == foldl f z $ concat xs. With snoc a b = a++[b],
Prelude> (foldl.foldl) snoc [] [[1..3],[4..6],[7..8]]
[1,2,3,4,5,6,7,8]
Also, (foldl.foldl.foldl) f z xs == (foldl.foldl) (foldl f) z xs == foldl (foldl f) z $ concat xs == (foldl.foldl) f z $ concat xs == foldl f z $ concat (concat xs), etc.:
Prelude> (foldl.foldl.foldl) snoc [] [[[1..3],[4..6]],[[7..8]]]
[1,2,3,4,5,6,7,8]
Prelude> (foldl.foldr.foldl) snoc [] [[[1..3],[4..6]],[[7..8]]]
[7,8,1,2,3,4,5,6]
Prelude> (foldl.foldl.foldr) (:) [] [[[1..3],[4..6]],[[7..8]]]
[7,8,4,5,6,1,2,3]

Resources