Which of the following are you most likely to write?
r = zip xs $ map sqrt xs
or
r = [(x, sqrt x) | x <- xs]
Sample code on the Internet seems to indicate that the former is more abundant and the preferred way.
Which of the following are you most likely to write?
r = zip xs $ map sqrt xs
or
r = [(x, sqrt x) | x <- xs]
Sample code on the Internet seems to indicate that the former is more abundant and the preferred way.
I rarely use list comprehensions, but both are dandy. Just use the one that makes your code easier to read.
People who spend too much time in #haskell would probably write that as
r = map (id &&& sqrt) xs
(&&&)
is a fun combinator defined in Control.Arrow
. Its actual type signature is complicated because it's generalized to all instances of Arrow. But it's often used with the (->)
instance of Arrow
, which results in this type signature:
(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c)
Although I tend to not use them very often, in this case, I think I'd prefer the list comprehension version, since it seems cleaner to me.
If you're into point free style, you might like this one, too:
f = zip `ap` map sqrt
ap lives in Control.Monad and in this case, it can be thought of as the S combinator, which generalizes application in SKI calculus:
ap f g x == f x (g x)
ap const const == id
As Conal points out, this may also be generalized from Monad to Applicative thusly (import Control.Applicative):
f = zip <*> map sqrt
I would probably write map
/zip
and then later wish I had written the list comprehension.
For certain types of problems (Project Euler in particular), this particular case comes up so often that I wrote the following little helper:
with :: (a -> b) -> a -> (a,b)
with f a = (a, f a)
This allows your example to be written:
r = map (with sqrt) xs
I'm more of an "Old School" Haskellier, so I'd use zip `ap` map sqrt
and later refactor it to use the <*>
instead of ap
.
Applicative is the new Monad. (In the sense of "what do the Cool Haskell Kids use these days?")
I'd likely write
map (\x -> (x, sqrt x)) xs
If you prefer point-free, the above is equivalent to (after having imported Control.Monad
and Control.Monad.Instances
)
map (ap (,) sqrt) xs
Another alternative that hasn't yet been mentioned is
zipWith (,) xs (map sqrt xs)