Какое из следующего вы, скорее всего, напишете?
r = zip xs $ map sqrt xs
или
r = [(x, sqrt x) | x <- xs]
Пример кода в Интернете, по-видимому, указывает на то, что первое является более распространенным и предпочтительным.
Какое из следующего вы, скорее всего, напишете?
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. Но он часто используется с экземпляром (->)
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 в эти дни?" )