2012-01-05 4 views
2

Я действительно новичок в Haskell, и я застрял в попытке сопоставить первый элемент каждой пары в списке.Картирование с парами

Очевидно, что это работает:

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

Но как мне заставить его работать на

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

Я просто хочу, чтобы игнорировать значения Int сейчас и применить е к, как это делает в первом примере. Я пробовал целую вечность, поэтому спасибо за любую помощь.

+0

спасибо так много, что он работает – user1131194

+0

Если ответ помог вам, пожалуйста, нажмите на галочку рядом с ним, чтобы пометить его как принято:) – ehird

ответ

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

+1, но вопрос имеет '(a -> b) -> [(a, Int)] -> [b]', а не '(a -> b) -> [(a, Int)] -> [(b, Int)] '. – ehird

+0

@ehird: Да, но вопрос, о котором мы упоминали, игнорируя значения «Int» на данный момент », поэтому было полезно включить обе версии, пока я был на ней. –

+0

Ах, не понял, что у вас есть «mapFst». – ehird

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

читать справа налево: в map fst извлекает все первые значения, то map f применяет функцию к каждому первому значению.

+3

+1, но 'map (f. Fst)' лучше (особенно если вы хотите изучить Int в будущем). – ehird

+0

'mapFirst :: (a -> b) -> [(a, c)] -> [(b, c)]; mapFirst = map. первая, вдохновленная [комбинаторами семантического редактора] (http://conal.net/blog/posts/semantic-editor-combinators), является аналогичной функцией, о которой нужно подумать. –

+0

@ehird - как это лучше, и что это связано с изучением 'snd' части кортежа? Я думал, что «назови карту». карта bar' всегда может быть оптимизирована в 'map (foo. bar)' без разницы в производительности, кроме 1 прохода вместо 2 над списком. –

2

Прямым продолжением того, что у вас уже есть, используя списочные:

map' :: (a -> b) -> [(a, Int)] -> [b] 
map' f xs = [ f x | (x, _) <- xs ] 
Смежные вопросы