我经常使用这个:
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])
) 的东西。