Haskell carte / zip Vs. la compréhension de la liste
-
02-10-2019 - |
Question
Lequel des éléments suivants vous sont les plus susceptibles d'écrire?
r = zip xs $ map sqrt xs
ou
r = [(x, sqrt x) | x <- xs]
Exemple de code sur Internet semble indiquer que le premier est plus abondante et la façon préférée.
La solution
J'écrirait probablement
map (\x -> (x, sqrt x)) xs
Si vous préférez point libre, ce qui précède est équivalent à (après avoir importé Control.Monad
et Control.Monad.Instances
)
map (ap (,) sqrt) xs
Une autre alternative qui n'a pas encore été mentionné est
zipWith (,) xs (map sqrt xs)
Autres conseils
Les gens qui passent trop de temps à #haskell serait probablement écrire que
r = map (id &&& sqrt) xs
(&&&)
est un combinateur amusant défini dans Control.Arrow
. Sa signature de type réel est compliquée parce qu'il est généralisé à toutes les instances de la flèche. Mais il est souvent utilisé avec l'instance de (->)
de Arrow
, ce qui aboutit à cette signature de type:
(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c)
Bien que je tendance à ne pas les utiliser très souvent, dans ce cas, je pense que je préfère la version de compréhension de la liste, car il me semble plus propre.
Si vous êtes dans le point de style libre, vous pourriez comme celui-ci aussi:
f = zip `ap` map sqrt
vit ap à Control.Monad et dans ce cas, il peut être considéré comme le S Combinator, qui généralise l'application dans SKI calcul :
ap f g x == f x (g x)
ap const const == id
Comme Conal souligne, cela peut également être généralisé de Monad à Applicative thusly (import de Control.Applicative):
f = zip <*> map sqrt
Je map
probablement écrire / zip
et souhaite plus tard, je l'avais écrit la compréhension de la liste.
Pour certains types de problèmes ( Projet Euler en particulier), ce cas particulier arrive si souvent que je l'ai écrit la après avoir connu une aide:
with :: (a -> b) -> a -> (a,b)
with f a = (a, f a)
Cela permet à votre exemple à écrire:
r = map (with sqrt) xs
Je suis plus d'une « vieille école » Haskellier, donc j'utiliser zip `ap` map sqrt
puis refactoriser utiliser le <*>
au lieu de ap
.
Applicative est le nouveau Monad. (Au sens de « qu'est-ce que Cool Haskell Les enfants utilisent ces jours-ci? »)
J'utilise rarement compréhensions de la liste, mais les deux sont dandy. Il suffit d'utiliser celui qui rend votre code plus facile à lire.