11

我经常使用这个:

a' = [ (f x, f y) | (x, y) <- a ]

有没有更好的方法来做到这一点?

4

3 回答 3

14

您可以使用(***)运算符Control.Arrow

> map (f *** f) a

或定义自己的辅助函数

> let both f (x, y) = (f x, f y)
> map (both f) a
于 2012-10-23T02:38:07.820 回答
11

替代解决方案:

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)

(,)如果您经常使用相同元素类型对,那么切换到这种类型可能会很有用。

于 2012-10-23T06:30:52.820 回答
5

如果使用lens,则可以使用over both f, 或both %~ f。这具有更易于组合的优点——例如,如果您有一对列表,您可以使用类似both.mapped +~ toUpper( :: ([Char],[Char]) -> ([Char],[Char])) 的东西。

于 2012-10-23T06:21:48.383 回答