用对映射

时间:2012-01-05 02:06:30

标签: haskell

我是Haskell的新手,我一直试图在列表中映射每对的第一项。

显然这有效:

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

但我如何让它为

工作
map :: (a -> b) -> [(a, Int)] -> [b]

我只是想让它暂时忽略Int值并将f应用到第一个例子中。我现在已经尝试了很多年,所以感谢任何帮助。

3 个答案:

答案 0 :(得分:8)

好吧,假设你不想使用内置函数map,从这开始:

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

要接受类型[(a, Int)]的列表并仅使用a,您可以模式匹配元组:

map :: (a -> b) -> [(a, Int)] -> [b]
map f xs = [f x | (x, y) <- xs]

如果你想保留Int,你可以在之后重新组合:

map :: (a -> b) -> [(a, Int)] -> [(b, Int)]
map f xs = [(f x, y) | (x, y) <- xs]

但所有这些都有点多余。您可以通过将参数更改为原始的map

来完成相同的操作
map :: (a -> b) -> [a] -> [b]
map f xs = [f x | x <- xs]

mapFst :: (a -> b) -> [(a, Int)] -> [b]
mapFst f xs = map (f . fst) xs

mapOnFirst :: (a -> b) -> [(a, Int)] -> [(b, Int)]
mapOnFirst f xs = map (\(x,y) -> (f x, y)) xs

对于第三个版本,标准库的模块Control.Arrow为您提供了一个名为first的函数,可用于获得相同的效果:

mapOnFirst :: (a -> b) -> [(a, Int)] -> [(b, Int)]
mapOnFirst f xs = map (first f) xs

干净,呵呵?

答案 1 :(得分:2)

mapfst :: (a -> b) -> [(a, c)] -> [b]
mapfst f = map f . map fst

从右到左阅读:map fst提取所有第一个值,然后map f将函数应用于每个第一个值。

答案 2 :(得分:2)

使用列表推导直接扩展您已有的内容:

map' :: (a -> b) -> [(a, Int)] -> [b]
map' f xs = [ f x | (x, _) <- xs ]