是否有更好的方法将函数应用于列表中的一对元素而不是列表推导?

时间:2012-10-23 02:27:33

标签: haskell

我使用了这一点:

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

有更好的方法吗?

3 个答案:

答案 0 :(得分:14)

您可以使用(***)

中的Control.Arrow运算符
> map (f *** f) a

或定义自己的帮助函数

> let both f (x, y) = (f x, f y)
> map (both f) a

答案 1 :(得分:11)

替代解决方案:

import Data.Bifunctor

bimap f f pair

Bifunctor.bimapArrow.(***)基本相同,但也适用于其他bifunctors(如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)

如果您使用相同元素类型对进行了大量工作,那么从(,)切换到这样的类型可能会很有用。

答案 2 :(得分:5)

如果您使用lens,则可以使用over both fboth %~ f。这具有更易组合的优势 - 例如,如果您有一对列表,则可以使用both.mapped +~ toUpper:: ([Char],[Char]) -> ([Char],[Char]))之类的内容。