Карта Haskell / zip vs. Список понимания
-
02-10-2019 - |
Вопрос
Что из следующего вы, скорее всего, напишу?
r = zip xs $ map sqrt xs
или
r = [(x, sqrt x) | x <- xs]
Образец кода в Интернете, кажется, указывает на то, что первый является более обильным и предпочтительным способом.
Решение
Я, скорее всего, напишу
map (\x -> (x, sqrt x)) xs
Если вы предпочитаете без уточнения, вышеизложенное эквивалентно (после импортированного Control.Monad
и Control.Monad.Instances
)
map (ap (,) sqrt) xs
Еще одна альтернатива, которая еще не упомянута,
zipWith (,) xs (map sqrt xs)
Другие советы
Люди, которые проводят слишком много времени в #haskell, вероятно, написали бы, что
r = map (id &&& sqrt) xs
(&&&)
это интересный комбинатор, определенный в Control.Arrow
. Отказ Его фактическая подпись типа сложна, поскольку она обобщена всем экземплярам стрелки. Но это часто используется с (->)
случай Arrow
, что приводит к этой типу подписи:
(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c)
Хотя я склонен не использовать их очень часто, в этом случае, я думаю, я бы предпочел версию понимания списка, поскольку это кажется уборщиком для меня.
Если вы в моменте свободный стиль, вам может понравиться это тоже:
f = zip `ap` map sqrt
AP живет в управлении .Monad и в этом случае его можно рассматривать как комбинатор S, который обобщает применение в Ski Calculus.:
ap f g x == f x (g x)
ap const const == id
Как отмечает Conal, это также может быть обобщена от монады до примерятельного (контроль импорта.
f = zip <*> map sqrt
Я бы, наверное, написал map
/zip
А потом позже желаю написать список списков.
Для определенных типов проблем (Проект Эйлер В частности), этот конкретный случай возникает так часто, что я написал следующий маленький помощник:
with :: (a -> b) -> a -> (a,b)
with f a = (a, f a)
Это позволяет вашему примеру быть написанным:
r = map (with sqrt) xs
Я больше «старой школы» хаскаклелл, поэтому я бы использовал zip `ap` map sqrt
и позже рефакторет его использовать <*>
вместо ap
.
Применитель - новый монад. (В смысле «что используют классные детские дети?»)
Я редко использую список списков, но оба являются DANDY. Просто используйте тот, который облегчает чтение вашего кода.