我是Haskell的新手,我一直试图在列表中映射每对的第一项。
显然这有效:
map :: (a -> b) -> [a] -> [b]
map f xs = [f x | x <- xs]
但我如何让它为
工作map :: (a -> b) -> [(a, Int)] -> [b]
我只是想让它暂时忽略Int值并将f应用到第一个例子中。我现在已经尝试了很多年,所以感谢任何帮助。
答案 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 ]