Карта/zip Haskell По сравнению с пониманием списка

Какое из следующего является Вами, скорее всего, для записи?

r = zip xs $ map sqrt xs

или

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

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

19
задан Will Ness 28 October 2013 в 20:01
поделиться

7 ответов

Скорее всего, я напишу

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

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

map (ap (,) sqrt) xs

Другой альтернативой, которая еще не упоминалась, является

zipWith (,) xs (map sqrt xs)
10
ответ дан 30 November 2019 в 01:50
поделиться

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

r = map (id &&& sqrt) xs

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

(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c)
25
ответ дан 30 November 2019 в 01:50
поделиться

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

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

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

r = map (with sqrt) xs
10
ответ дан 30 November 2019 в 01:50
поделиться

Я редко использую понимания списков, но оба варианта хороши. Просто используйте ту, которая облегчает чтение вашего кода.

6
ответ дан 30 November 2019 в 01:50
поделиться

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

12
ответ дан 30 November 2019 в 01:50
поделиться

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

Если вам нравится безточечный стиль, вам тоже может понравиться этот:

f = zip `ap` map sqrt

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

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

Как указывает Конал, это также может быть обобщено от Monad до Applicative таким образом (import Control.Applicative):

f = zip <*> map sqrt
16
ответ дан 30 November 2019 в 01:50
поделиться

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

Аппликатив - это новая монада. (В смысле «что используют Cool Haskell Kids в наши дни?»)

7
ответ дан 30 November 2019 в 01:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: