Define map using foldl instead of foldr and an expr - haskell

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

Related

Why foldr (\ x xs -> x : x : xs) [] wont work?

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 ++.

Why does zipWith.zipWith work?

I am implementing a function combine :: [[a]] -> [[b]] -> (a -> b -> c) -> [[c]] which given two 2D lists, applies a given function f :: a -> b -> c to the entries of the 2D list. In other words:
[[a, b, c], [[r, s, t], [[f a r, f b s, f c t],
combine [d, e, g], [u, v, w], f = [f d u, f e v, f g w],
[h, i, j]] [x, y, z]] [f h x, f i y, f j z]]
Now I suspect that combine = zipWith . zipWith, because I have tried it out and it is giving me the intended results, e.g.
(zipWith . zipWith) (\x y -> x+y) [[1,2,3],[4,5,6]] [[7,8,9],[10,11,12]]
gives the expected result [[8,10,12],[14,16,18]], but I cannot understand why this works, because I don't understand how the type of zipWith . zipWith turns out to be (a -> b -> c) -> [[a]] -> [[b]] -> [[c]].
Is (.) here still carrying out the usual function composition? If so, can you explain how this applies to zipWith?
To infer the type of an expression such as zipWith . zipWith, you can simulate the unification in your head the following way.
The first zipWith has type (a -> b -> c) -> ([a] -> [b] -> [c]), the second (s -> t -> u) -> ([s] -> [t] -> [u]) and (.) has type (m -> n) -> (o -> m) -> (o -> n).
For it to typecheck, you need:
m = (a -> b -> c)
n = ([a] -> [b] -> [c])
o = (s -> t -> u)
m = ([s] -> [t] -> [u]) => a = [s], b = [t], c = [u] because of the first constraint
Then the returned type is o -> n which is (s -> t -> u) -> ([a] -> [b] -> [c]) from the constraints and going one step further (s -> t -> u) -> ([[s]] -> [[t]] -> [[u]]).
Another way of seeing it is that lists with the zipping operation form an Applicative, and the composition (nesting) of Applicatives is still Applicative:
λ import Control.Applicative
λ import Data.Functor.Compose
λ let l1 = ZipList [ZipList [1,2,3], ZipList [4,5,6]]
λ let l2 = ZipList [ZipList [7,8,9], ZipList [10,11,12]]
λ getCompose $ (+) <$> Compose l1 <*> Compose l2
ZipList {getZipList = [ZipList {getZipList = [8,10,12]},
ZipList {getZipList = [14,16,18]}]}
The ZipList newtype is required because "bare" lists have a different Applicative instance, which forms all combinations instead of zipping.
Yes, . is the normal function composition operator:
Prelude> :type (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
One way to look at it is that it takes an a value, first calls the a -> b function, and then uses the return value of that function to call the b -> c function. The result is a c value.
Another way to look at (zipWith . zipWith), then, is to perform an eta expansion:
Prelude> :type (zipWith . zipWith)
(zipWith . zipWith) :: (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
Prelude> :t (\x -> zipWith $ zipWith x)
(\x -> zipWith $ zipWith x)
:: (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
Prelude> :t (\x -> zipWith (zipWith x))
(\x -> zipWith (zipWith x))
:: (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
The type of zipWith itself:
Prelude> :type zipWith
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
So, in the above lambda expression, x must be (a -> b -> c), and hence zipWith x must have the type [a] -> [b] -> [c].
The outer zipWith also needs a function (a1 -> b1 -> c1), which matches zipWith x if a1 is [a], b1 is [b], and c1 is [c].
So, by replacement, zipWith (zipWith x) must have the type [[a]] -> [[b]] -> [[c]], and therefore the type of the lambda expression is (a -> b -> c) -> [[a]] -> [[b]] -> [[c]].

map function using foldl or foldr in Haskell

I am writing a function my_map which takes a unary function and a list and returns the list resulting from mapping the function over all elements of the input list.
Main> my_map (^3) [1..5]
[1,8,27,64,125]
I tried it like this:
my_map :: (a -> b) -> [a] -> [b]
my_map f [] = []
my_map f (x:xs) = foldr (\x xs -> (f x):xs) [] xs
But after running above, I get only [8,27,64,125]. the first number 1 is not displaying in output.
Can anybody help me?
You are using the (x:xs) pattern in your arguments, but when you apply the fold, you only apply it to the xs part, which means your first element i.e. the one that x represents never gets processed. You need to change it to this:
my_map :: (a -> b) -> [a] -> [b]
my_map f xs = foldr (\y ys -> (f y):ys) [] xs
Since you are using foldr, you do not need to explicitly handle the empty list case. Moreoever, you do not need to specify the list in (x:xs) format.
Finally, my own preference is to avoid using the same name for function inputs and any helper functions or expressions in the function definition.That is why, I have used xs for the input list and y and ys for the parameters passed to the lambda.
"shree.pat18" is perfectly right, and also the comments are valuable. I learned a lot from that. Just make it better visible, and to explain the alternatives...
Answer
-- The problem is here ....................... vv
my_map f (x:xs) = foldr (\x xs -> (f x):xs) [] xs
-- --
The remaining part xs is aplied to foldr.
To fix just this, apply the whole list. This can be done by placing xx# before (x:xs). By that, the whole list is bound to xx.
-- vvv ........... see here ............... vv
my_map f xx#(x:xs) = foldr (\x xs -> (f x):xs) [] xx
-- --- --
Recommended impovement
Note: foldr can already deal with [] as input. Hence, my_map f [] = [] is not needed. But foldr would not be called when you apply [] to my_map. To get rid of my_map f [] = [], you need to remove the pattern matching, because (x:xs) matches only to lists with at least one element.
main :: IO ()
main = print $ my_map (^(3 :: Int)) ([1..5] :: [Integer])
my_map :: (a -> b) -> [a] -> [b]
my_map f xx = foldr (\x xs -> (f x):xs) [] xx
The answer is complete here. The rest below is for pleasure.
Further reductions
Simple expression instead of lambda expression
If you want to reduce the lambda expression (\x xs -> (f x):xs), as suggested by "Aadit M Shah"...
(:) is equal to (\x xs -> x:xs), because : is an operator and its function is (:)
. can be used to combine the function f with (:), hence (\x xs -> (f x):xs) is equal to ((:) . f)
main :: IO ()
main = print $ my_map (^(3 :: Int)) ([] :: [Integer])
my_map :: (a -> b) -> [a] -> [b]
my_map f xx = foldr ((:) . f) [] xx
Currying
A function of the form
-- v v
f a b c = .... c
can be reduced to
-- v v
f a b = ....
and a function of the form
-- v v v v
f a b c = .... b c
can be reduced to
-- v v v v
f a = ....
and so on, by currying.
Hence, my_map f xx = foldr ((:) . f) [] xx equals my_map f = foldr ((:) . f) [].
Combination and flip
flip flips the first two parameters.
Example, the following functions are equal:
f' a b c = (\c' b' a' -> ((a' - b') / c')) b a c
f'' a b c = flip (\c' b' a' -> ((a' - b') / c')) a b c
f''' = flip (\c' b' a' -> ((a' - b') / c'))
Hence, the following code works as well.
main :: IO ()
main = print $ my_map (^(3 :: Int)) ([1..5] :: [Integer])
my_map :: (a -> b) -> [a] -> [b]
my_map f = flip foldr [] ((:) . f)
But we can not get rid of f as above, because of the form in the expression flip foldr [] ((:) . f).
If we remove f ...
`((:) . f)` has type `a -> [a] -> [a]
-- v
`((:) . )` has type `(a -> a) -> a -> [a] -> [a]`
and
`flip foldr []` has type `Foldable t => (a1 -> [a2] -> [a2]) -> t a1 -> [a2]`
hence
f :: a -> a
is passed to
((:) . )
becomming
a -> [a] -> [a]
is passed to
flip foldr []
becomming
t a1 -> [a2]
Hence,
main :: IO ()
main = print $ my_map (^(3 :: Int)) ([1..5] :: [Integer])
my_map :: (a -> b) -> [a] -> [b]
my_map = flip foldr [] . ((:) . )
works nicely.

Why can't I compose before currying two arguments? [duplicate]

I am trying to compose a function of type (Floating a) => a -> a -> a with a function of type (Floating a) => a -> a to obtain a function of type (Floating a) => a -> a -> a. I have the following code:
test1 :: (Floating a) => a -> a -> a
test1 x y = x
test2 :: (Floating a) => a -> a
test2 x = x
testBoth :: (Floating a) => a -> a -> a
testBoth = test2 . test1
--testBoth x y = test2 (test1 x y)
However, when I compile it in GHCI, I get the following error:
/path/test.hs:8:11:
Could not deduce (Floating (a -> a)) from the context (Floating a)
arising from a use of `test2'
at /path/test.hs:8:11-15
Possible fix:
add (Floating (a -> a)) to the context of
the type signature for `testBoth'
or add an instance declaration for (Floating (a -> a))
In the first argument of `(.)', namely `test2'
In the expression: test2 . test1
In the definition of `testBoth': testBoth = test2 . test1
Failed, modules loaded: none.
Note that the commented-out version of testBoth compiles. The strange thing is that if I remove the (Floating a) constraints from all type signatures or if I change test1 to just take x instead of x and y, testBoth compiles.
I've searched StackOverflow, Haskell wikis, Google, etc. and not found anything about a restriction on function composition relevant to this particular situation. Does anyone know why this is happening?
\x y -> test2 (test1 x y)
== \x y -> test2 ((test1 x) y)
== \x y -> (test2 . (test1 x)) y
== \x -> test2 . (test1 x)
== \x -> (test2 .) (test1 x)
== \x -> ((test2 .) . test1) x
== (test2 .) . test1
These two things are not like each other.
test2 . test1
== \x -> (test2 . test1) x
== \x -> test2 (test1 x)
== \x y -> (test2 (test1 x)) y
== \x y -> test2 (test1 x) y
You're problem doesn't have anything to do with Floating, though the typeclass does make your error harder to understand. Take the below code as an example:
test1 :: Int -> Char -> Int
test1 = undefined
test2 :: Int -> Int
test2 x = undefined
testBoth = test2 . test1
What is the type of testBoth? Well, we take the type of (.) :: (b -> c) -> (a -> b) -> a -> c and turn the crank to get:
b ~ Int (the argument of test2 unified with the first argument of (.))
c ~ Int (the result of test2 unified with the result of the first argument of (.))
a ~ Int (test1 argument 1 unified with argument 2 of (.))
b ~ Char -> Int (result of test1 unified with argument 2 of (.))
but wait! that type variable, 'b' (#4, Char -> Int), has to unify with the argument type of test2 (#1, Int). Oh No!
How should you do this? A correct solution is:
testBoth x = test2 . test1 x
There are other ways, but I consider this the most readable.
Edit: So what was the error trying to tell you? It was saying that unifying Floating a => a -> a with Floating b => b requires an instance Floating (a -> a) ... while that's true, you really didn't want GHC to try and treat a function as a floating point number.
Your problem has nothing to do with Floating, but with the fact that you want to compose a function with two arguments and a function with one argument in a way that doesn't typecheck. I'll give you an example in terms of a composed function reverse . foldr (:) [].
reverse . foldr (:) [] has the type [a] -> [a] and works as expected: it returns a reversed list (foldr (:) [] is essentially id for lists).
However reverse . foldr (:) doesn't type check. Why?
When types match for function composition
Let's review some types:
reverse :: [a] -> [a]
foldr (:) :: [a] -> [a] -> [a]
foldr (:) [] :: [a] -> [a]
(.) :: (b -> c) -> (a -> b) -> a -> c
reverse . foldr (:) [] typechecks, because (.) instantiates to:
(.) :: ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
In other words, in type annotation for (.):
a becomes [a]
b becomes [a]
c becomes [a]
So reverse . foldr (:) [] has the type [a] -> [a].
When types don't match for function composition
reverse . foldr (:) doesn't type check though, because:
foldr (:) :: [a] -> [a] -> [a]
Being the right operant of (.), it would instantiate its type from a -> b to [a] -> ([a] -> [a]). That is, in:
(b -> c) -> (a -> b) -> a -> c
Type variable a would be replaced with [a]
Type variable b would be replaced with [a] -> [a].
If type of foldr (:) was a -> b, the type of (. foldr (:)) would be:
(b -> c) -> a -> c`
(foldr (:) is applied as a right operant to (.)).
But because type of foldr (:) is [a] -> ([a] -> [a]), the type of (. foldr (:)) is:
(([a] -> [a]) -> c) -> [a] -> c
reverse . foldr (:) doesn't type check, because reverse has the type [a] -> [a], not ([a] -> [a]) -> c!
Owl operator
When people first learn function composition in Haskell, they learn that when you have the last argument of function at the right-most of the function body, you can drop it both from arguments and from the body, replacing or parentheses (or dollar-signs) with dots. In other words, the below 4 function definitions are equivalent:
f a x xs = g ( h a ( i x xs))
f a x xs = g $ h a $ i x xs
f a x xs = g . h a . i x $ xs
f a x = g . h a . i x
So people get an intuition that says “I just remove the right-most local variable from the body and from the arguments”, but this intuition is faulty, because once you removed xs,
f a x = g . h a . i x
f a = g . h a . i
are not equivalent! You should understand when function composition typechecks and when it doesn't. If the above 2 were equivalent, then it would mean that the below 2 are also equivalent:
f a x xs = g . h a . i x $ xs
f a x xs = g . h a . i $ x xs
which makes no sense, because x is not a function with xs as a parameter. x is a parameter to function i, and xs is a parameter to function (i x).
There is a trick to make a function with 2 parameters point-free. And that is to use an “owl” operator:
f a x xs = g . h a . i x xs
f a = g . h a .: i
where (.:) = (.).(.)
The above two function definitions are equivalent. Read more on “owl” operator.
References
Haskell programming becomes much easier and straightforward, once you understand functions, types, partial application and currying, function composition and dollar-operator. To nail these concepts, read the following StackOverflow answers:
On types and function composition
On higher-order functions, currying, and function composition
On Haskell type system
On point-free style
On const
On const, flip and types
On curry and uncurry
Read also:
Haskell: difference between . (dot) and $ (dollar sign)
Haskell function composition (.) and function application ($) idioms: correct use

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".

Resources