2012-10-23 4 views

Antwort

14

Sie können das (***) Betreiber von Control.Arrow

> map (f *** f) a 

oder Ihre eigene Hilfsfunktion

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

oder vielleicht nur ein Lambda: 'map (\ (x, y) -> (fx, fy)) a' – MtnViewMark

5

definieren Wenn Sie lens verwenden, Sie over both f oder both %~ f verwenden können. Dies hat den Vorteil, dass es besser zusammensetzbar ist. Wenn Sie zum Beispiel ein Listenpaar haben, können Sie etwas wie both.mapped +~ toUpper (:: ([Char],[Char]) -> ([Char],[Char])) verwenden.

11

Alternative Lösung:

import Data.Bifunctor 

bimap f f pair 

Bifunctor.bimap ist grundsätzlich die gleiche wie Arrow.(***), funktioniert aber für andere bifunctors (wie Either a b) auch.

Exkurs:

Der Grund, warum es nichts für Ihren Fall vorgegeben ist, dass Sie keine Instanzen von Functor, für (,)Applicative etc schreiben kann das gleiche Element zweimal eingeben zu müssen. Mit einem eigenen „Vektor-like“ Typ würden Sie dieses Problem nicht:

data Pair a = Pair a a deriving Show 

instance Functor Pair where 
    fmap f (Pair x y) = Pair (f x) (f y) 

Jetzt können Sie Dinge wie map (fmap (+1)) [Pair 12 14, Pair 17 18] schreiben. Oder wenn Sie verschiedene Vorgänge auf Ihrem Pair verwenden möchten, können Sie noch einen Schritt weiter gehen:

instance Applicative Pair where 
    pure x = Pair x x 
    (Pair f g) <*> (Pair x y) = Pair (f x) (g y) 

Wenn Sie viel mit dem gleichen Elementtyp Paare arbeiten, könnte es sinnvoll sein, wechseln von (,) auf eine solche Art.

+0

Danke für den Exkurs. –

Verwandte Themen