我经常使用这个:
a' = [ (f x, f y) | (x, y) <- a ]
有没有更好的方法来做到这一点?
您可以使用(***)运算符Control.Arrow
> map (f *** f) a
或定义自己的辅助函数
> let both f (x, y) = (f x, f y)
> map (both f) a
替代解决方案:
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)
(,)如果您经常使用相同元素类型对,那么切换到这种类型可能会很有用。
如果使用lens,则可以使用over both f, 或both %~ f。这具有更易于组合的优点——例如,如果您有一对列表,您可以使用类似both.mapped +~ toUpper( :: ([Char],[Char]) -> ([Char],[Char])) 的东西。