私はこれをかなり使用します:
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
などのインスタンスを2回書き込むことができないためです。(,)
独自の「ベクトルのような」タイプを使用すると、この問題は発生しません。
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])