[英]Use foldr to define map in Haskell,
I'm new to Haskell and try to understand the map function. 我是Haskell的新手,并尝试了解map函数。
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
的来源 :
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
的定义与go
的定义进行比较:
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: 让我们重写第二个子句,以提取将
x
与递归调用的结果结合在一起的部分:
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! 只需替换
go
在上面看到map f
任何地方,您就会看到定义是相同的! So in the spirit of DRY, we can try to reuse foldr
for the above: 因此,本着DRY的精神,我们可以尝试将
foldr
重复用于以上内容:
map f = foldr (\v vs -> f v : vs) []
That gets you the big idea on how to get from map
to foldr
. 这使您对如何从
map
到文件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: 现在,我们将重点介绍
foldr
的function参数:
\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
. foldr fz xs
替换每:
在xs
与f
,并[]
与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'
. 现在,让我们从
map'
的定义中替换值。
a `(:).f` b `(:).f` c `(:).f` d `(:).f` []
(I'm stretching the Haskell syntax a bit). (我在扩展Haskell语法)。
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? 嘿,这看起来像是将直线
map f
应用于[a,b,c,d]
,不是吗?
First you need to understand 首先你需要了解
foldr (:) []
the other one is just applying function f
before cons, therefore equivalent to map 另一个只是在缺点之前应用函数
f
,因此等效于map
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.