使用foldr在Haskell中定义地图,

时间:2016-05-19 01:13:13

标签: haskell

我是Haskell的新手并尝试了解地图功能。

到目前为止我理解以下内容。

map::(a->b)->[a]->[b]
map f (x:xs) = f x : map f xs

但我不明白以下定义: 使用 foldr 定义地图

map'::(a->b)->[a]->[b]
map' f = foldr ( (:).f ) []

任何人都可以解释上面的地图'定义以及为什么与地图相同

3 个答案:

答案 0 :(得分:5)

让我们看一下the source of foldr

foldr k z = go where
    go []     = z
    go (x:xs) = k x (go xs)

现在让我们将map的定义与上面go的定义进行比较:

map f []     = []
map f (x:xs) = f x : map f xs
它看起来非常相似,不是吗?让我们重写第二个子句,将x与递归调用结果相结合的部分拉出来:

map f []     = []
map f (x:xs) = (\v vs -> f v : vs) x (map f xs)

现在平行非常清楚;我们甚至可以写一些名字来结晶并行:

map f []     = z              where z = []
map f (x:xs) = k x (map f xs) where k = \v vs -> f v : vs

只需在上面看到go的任何地方替换map f,您就会看到定义相同!因此,本着DRY的精神,我们可以尝试重用foldr来实现上述目标:

map f = foldr (\v vs -> f v : vs) []

这让您了解如何从map转到foldr。一直到你给出的定义只是一些语法技巧。我们现在专注于foldr的函数参数:

\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

因此,使用这种推理链,我们可以达到最终形式

map f = foldr ((:) . f) []

答案 1 :(得分:3)

另一个答案,希望某些人更容易获得。

foldr f z xs:中的xs替换为f,将[]替换为z。所以

 a : b : c : d : []

成为

 a `f` b `f` c `f` d `f` z

现在让我们从map'的定义中替换值。

a `(:).f` b `(:).f` c `(:).f` d `(:).f` []

(我稍微扩展了Haskell语法)。

现在,

a `(:).f` as

相同
(:) (f a) as

相同
f a : as

继续这种转变,我们得到了

f a : f b : f c : f d : []

嘿,这似乎是直接map f应用于[a,b,c,d],不是吗?

答案 2 :(得分:0)

首先你需要了解

passwordText

另一个是在cons之前应用函数foldr (:) [] ,因此相当于map

相关问题