2012-10-23 9 views

risposta

14

È possibile utilizzare l'operatore (***) da Control.Arrow

> map (f *** f) a 

o definire la propria funzione di supporto

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

o forse solo un lambda: 'map (\ (x, y) -> (f x, f y)) a' – MtnViewMark

5

Se si utilizza lens, è possibile utilizzare over both f, o both %~ f. Questo ha il vantaggio di essere più componibile - ad esempio, se si dispone di un paio di elenchi, è possibile utilizzare qualcosa come both.mapped +~ toUpper (:: ([Char],[Char]) -> ([Char],[Char])).

11

Soluzione alternativa:

import Data.Bifunctor 

bimap f f pair 

Bifunctor.bimap è fondamentalmente lo stesso come Arrow.(***), ma funziona per altri bifunctors (come Either a b), anche.

Digressione:

Il motivo per cui non c'è nulla di predefinito per il vostro caso è che non si può scrivere istanze di Functor, Applicative ecc per (,) avere tipo due volte lo stesso elemento. Con un proprio tipo "vettore-like" non avrebbe questo problema:

data Pair a = Pair a a deriving Show 

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

Ora è possibile scrivere le cose come map (fmap (+1)) [Pair 12 14, Pair 17 18]. Oppure, se si desidera utilizzare diverse operazioni sul Pair, si può fare un passo avanti:

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

Se si lavora molto con le coppie dello stesso elemento-tipo, potrebbe essere utile per passare da (,) a tale genere.

+0

Grazie per la divagazione. –

Problemi correlati