Io uso questo un bel po ':Esiste un modo migliore per applicare una funzione a entrambi gli elementi di una coppia in una lista rispetto alla comprensione di una lista?
a' = [ (f x, f y) | (x, y) <- a ]
C'è un modo migliore per farlo?
Io uso questo un bel po ':Esiste un modo migliore per applicare una funzione a entrambi gli elementi di una coppia in una lista rispetto alla comprensione di una lista?
a' = [ (f x, f y) | (x, y) <- a ]
C'è un modo migliore per farlo?
È 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
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])
).
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.
Grazie per la divagazione. –
o forse solo un lambda: 'map (\ (x, y) -> (f x, f y)) a' – MtnViewMark