Карта Haskell / почтовый индекс Vs. понимание списка
Что из следующего вы, скорее всего, напишите?
r = zip xs $ map sqrt xs
или же
r = [(x, sqrt x) | x <- xs]
Пример кода в Интернете, кажется, указывает на то, что первый является более распространенным и предпочтительным способом.
7 ответов
Я бы скорее написал
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. Но это часто используется с (->)
экземпляр Arrow
, что приводит к подписи этого типа:
(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c)
Хотя я склонен не использовать их очень часто, в этом случае, я думаю, я бы предпочел версию для понимания списка, так как она кажется мне чище.
Если вы любите стиль без точек, он вам тоже может понравиться:
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
Я бы наверное написал map
/zip
а потом позже хотелось бы, чтобы я написал список понимания.
Для определенных типов проблем (в частности, Project Euler) этот частный случай возникает так часто, что я написал следующий маленький помощник:
with :: (a -> b) -> a -> (a,b)
with f a = (a, f a)
Это позволяет вашему примеру быть написанным:
r = map (with sqrt) xs
Я больше из "старой школы" Haskellier, поэтому я бы использовал zip `ap` map sqrt
а затем рефакторинг, чтобы использовать <*>
вместо ap
,
Аппликативная новая монада. (В смысле "что используют Cool Haskell Kids в наши дни?")
Я редко использую списочные представления, но оба они превосходны. Просто используйте тот, который делает ваш код проще для чтения.