I'm new to Haskell and try to understand the map function.
I understand the following so far.
map::(a->b)->[a]->[b]
map f (x:xs) = f x : map f xs
But I don't understand following definition: Use foldr to define map
map'::(a->b)->[a]->[b]
map' f = foldr ( (:).f ) []
Can anyone explain the above map' definition and why it is same as map
Let's look at the source of foldr
:
foldr k z = go where
go [] = z
go (x:xs) = k x (go xs)
Now let's compare the definition of map
to the definition of go
above:
map f [] = []
map f (x:xs) = f x : map f xs
It looks very similar, doesn't it? Let's rewrite the second clause to pull out the part that combines x
with the recursive call's result:
map f [] = []
map f (x:xs) = (\v vs -> f v : vs) x (map f xs)
Now the parallel is very clear; we can even write some names to crystallize the parallel:
map f [] = z where z = []
map f (x:xs) = k x (map f xs) where k = \v vs -> f v : vs
Just substitute go
everywhere you see map f
in the above and you'll see that the definitions are identical! So in the spirit of DRY, we can try to reuse foldr
for the above:
map f = foldr (\v vs -> f v : vs) []
That gets you the big idea on how to get from map
to foldr
. Getting all the way to the definition you gave is then just some syntax tricks. We'll concentrate on the function argument to foldr
now:
\v vs -> f v : vs
= { writing the infix operator prefix instead }
\v vs -> (:) (f v) vs
= { eta reduction }
\v -> (:) (f v)
= { definition of function composition }
\v -> ((:) . f) v
= { eta reduction }
(:) . f
So using this chain of reasoning, we can reach the final form
map f = foldr ((:) . f) []
An alternate answer, hopefully more accessible to some people.
foldr fz xs
replaces every :
in xs
with f
, and []
with z
. So
a : b : c : d : []
becomes
a `f` b `f` c `f` d `f` z
Now let's substitute values from the definition of map'
.
a `(:).f` b `(:).f` c `(:).f` d `(:).f` []
(I'm stretching the Haskell syntax a bit).
Now,
a `(:).f` as
is the same as
(:) (f a) as
which is the same as
f a : as
Continuing wit this transformation, we get
f a : f b : f c : f d : []
Hey, this looks like straight map f
applied to [a,b,c,d]
, doesn't it?
First you need to understand
foldr (:) []
the other one is just applying function f
before cons, therefore equivalent to map
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.