Ich benutze dies ein gutes Stück:Gibt es einen schöneren Weg, um eine Funktion auf beide Elemente eines Paares in einer Liste anzuwenden als ein Listenverständnis?
a' = [ (f x, f y) | (x, y) <- a ]
Gibt es einen besseren Weg, dies zu tun?
Ich benutze dies ein gutes Stück:Gibt es einen schöneren Weg, um eine Funktion auf beide Elemente eines Paares in einer Liste anzuwenden als ein Listenverständnis?
a' = [ (f x, f y) | (x, y) <- a ]
Gibt es einen besseren Weg, dies zu tun?
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
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.
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.
Danke für den Exkurs. –
oder vielleicht nur ein Lambda: 'map (\ (x, y) -> (fx, fy)) a' – MtnViewMark