2010-07-04 7 views
18

Какое из следующего вы, скорее всего, напишете?Haskell map/zip Vs. list comprehension

r = zip xs $ map sqrt xs 

или

r = [(x, sqrt x) | x <- xs] 

Пример кода в Интернете, кажется, указывает, что первое является более обильными и предпочтительный способ.

ответ

9

Я бы скорее написать

map (\x -> (x, sqrt x)) xs 

Если вы предпочитаете точка свободна, то выше эквивалентно (после импортирован Control.Monad и Control.Monad.Instances)

map (ap (,) sqrt) xs 

Другой альтернативный, что hasn» t еще не упомянуто

6

Я редко использую списки, но оба они денди. Просто используйте тот, который упрощает чтение кода.

23

Люди, которые проводят слишком много времени в #haskell бы, вероятно, написать, что, как

r = map (id &&& sqrt) xs 

(&&&) весело комбинатор определено в Control.Arrow. Его фактическая сигнатура типа сложна, потому что она обобщена ко всем экземплярам Arrow. Но он часто используется с (->) экземпляром Arrow, что приводит к этому типу подписи:

(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c) 
+7

Я называю это «непрозрачным haskell». В определенный момент это просто неразборчиво, точка зависит от экспозиции. – Dan

+1

На самом деле я склонен определять функцию, которая из-за отсутствия лучшего имени я вызываю 'сохранение :: (a -> b) -> a -> (a, b)', определяемое как просто 'сохранение = (id &&&). (Иногда я также меняю порядок кортежей и определяю его как '(&& & id)'; Я должен быть последовательным.) Я всегда немного удивляюсь, что он, кажется, не выходит из любого стандарта. –

+8

Дэн, я думаю, что это, наверное, самый простой Комбинатор стрелок для использования в реальном коде. Его имя красиво запоминается: вы можете прочитать эту строку кода вслух, как «map id и sqrt to xs». – Carl

15

Хотя я, как правило, не использовать их очень часто, в этом случае, я думаю, что я бы предпочел вариант списка понимания, потому что мне кажется чище.

Если вы в безточечный, вы могли бы это одно, тоже:

f = zip `ap` map sqrt 

п.-п. жизнь в Control.Monad и в этом случае его можно рассматривать как S комбинатор, который обобщает применение в SKI calculus:

ap f g x == f x (g x) 
ap const const == id 

в Conal указует, это также может быть обобщенно от Монады до аппликативных констант выглядят (импорт Control.Applicative):

f = zip <*> map sqrt 
+1

милый, мне нравится эта нотация лучшая. Я всегда читаю «ap» как «apply», поэтому он становится: «zip apply map with sqrt to input» – Dan

+2

Или, упрощая/обобщая из «Monad» на «Applicative», 'f = zip <*> map sqrt'. Хотя я лично предпочитаю «map (id &&& sqrt) xs' как в ответе Carl. – Conal

+0

Да, это ИМХО хороший способ прочитать его. @Conal добавила ваше предложение к ответу. – danlei

11

Возможно, я бы написал map/zip, а затем пожелал, чтобы я написал список.

9

Для некоторых типов задач (Project Euler в частности), это частный случай приходит так часто, что я написал следующий маленький помощник:

with :: (a -> b) -> a -> (a,b) 
with f a = (a, f a) 

Это позволяет ваш пример будет написано:

r = map (with sqrt) xs 
6

Я больше из «старой школы» Хаскелли, поэтому я бы использовал zip `ap` map sqrt, а позже реорганизовал его, чтобы использовать <*> вместо ap.

Аппликационная новая Монада. (В смысле «что делают Cool Haskell Kids в эти дни?«)

+3

стрелы - новая монада, нет? –