Reputation: 41643
I use this a fair bit:
a' = [ (f x, f y) | (x, y) <- a ]
Is there a better way to do that?
Upvotes: 11
Views: 983
Reputation: 54584
Alternative solution:
import Data.Bifunctor
bimap f f pair
Bifunctor.bimap
is basically the same as Arrow.(***)
, but works for other bifunctors (like Either a b
), too.
Digression:
The reason why there is nothing predefined for your case is that you can't write instances of Functor
, Applicative
etc for (,)
having the same element type twice. With an own "vector-like" type you wouldn't have this problem:
data Pair a = Pair a a deriving Show
instance Functor Pair where
fmap f (Pair x y) = Pair (f x) (f y)
Now you can write things like map (fmap (+1)) [Pair 12 14, Pair 17 18]
. Or if you want to use different operations on your Pair
, you can go one step further:
instance Applicative Pair where
pure x = Pair x x
(Pair f g) <*> (Pair x y) = Pair (f x) (g y)
If you work a lot with same-element-type pairs, it could be useful to switch from (,)
to such a type.
Upvotes: 11
Reputation: 8930
If you use lens
, you can use over both f
, or both %~ f
. This has the advantage of being more composable -- for example, if you have a pair of lists, you can use something like both.mapped +~ toUpper
(:: ([Char],[Char]) -> ([Char],[Char])
).
Upvotes: 5
Reputation: 139850
You can use the (***)
operator from Control.Arrow
> map (f *** f) a
or define your own helper function
> let both f (x, y) = (f x, f y)
> map (both f) a
Upvotes: 15