или определите свою собственную вспомогательную функцию
> let both f (x, y) = (f x, f y)
> map (both f) a
Ответ 2
Альтернативное решение:
import Data.Bifunctor
bimap f f pair
Bifunctor.bimap в основном совпадает с Arrow.(***), но работает и для других бифункторов (например, Either a b).
Отступление:
Причина, по которой в вашем случае нет ничего предопределенного, заключается в том, что вы не можете писать экземпляры Functor, Applicative и т.д. для (,), имеющие один и тот же тип элемента дважды. С собственным "векторно-подобным" типом у вас не было бы этой проблемы:
data Pair a = Pair a a deriving Show
instance Functor Pair where
fmap f (Pair x y) = Pair (f x) (f y)
Теперь вы можете писать такие вещи, как map (fmap (+1)) [Pair 12 14, Pair 17 18]. Или, если вы хотите использовать разные операции на вашем Pair, вы можете пойти еще на один шаг:
instance Applicative Pair where
pure x = Pair x x
(Pair f g) <*> (Pair x y) = Pair (f x) (g y)
Если вы много работаете с парами одинакового типа, может быть полезно переключиться с (,) на такой тип.
Ответ 3
Если вы используете lens, вы можете использовать over both f или both %~ f. Преимущество этого состоит в том, что он более сложный - например, если у вас есть пара списков, вы можете использовать что-то вроде both.mapped +~ toUpper (:: ([Char],[Char]) -> ([Char],[Char])).