Paare sind im Wesentlichen wie folgt definiert:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Da die Art der Funktionsargumente und Ergebnisse müssen Art *
haben (dh sie repräsentieren:
data (,) a b = (,) a b
Die Functor
Klasse sieht wie folgt aus Werte statt Typ Funktionen, die weitere oder exotischere Dinge angewendet werden können), müssen wir haben a :: *
, b :: *
, und vor allem für unsere Zwecke, f :: * -> *
. Da (,)
die Art * -> * -> *
hat, muss sie auf einen Typ von Art *
angewendet werden, um einen Typ zu erhalten, der geeignet ist, ein Functor
zu sein. So
instance Functor ((,) x) where
-- fmap :: (a -> b) -> (x,a) -> (x,b)
So gibt es eigentlich keine Möglichkeit, eine Functor
Instanz schreiben etwas anderes zu tun.
Eine nützliche Klasse, die mehr Möglichkeiten bietet, mit Paaren zu arbeiten, ist Bifunctor
, von Data.Bifunctor
.
class Bifunctor f where
bimap :: (a -> b) -> (c -> d) -> f a c -> f b d
bimap f g = first f . second g
first :: (a -> b) -> f a y -> f b y
first f = bimap f id
second :: (c -> d) -> f x c -> f x d
second g = bimap id g
Auf diese Weise können Sie Dinge wie die folgenden (aus Data.Bifunctor.Join
) schreiben:
newtype Join p a =
Join { runJoin :: p a a }
instance Bifunctor p => Functor (Join p) where
fmap f = Join . bimap f f . runJoin
Join (,)
ist dann im Wesentlichen die gleiche wie Pair
, wo
data Pair a = Pair a a
Natürlich können Sie auch Verwenden Sie einfach die Bifunctor
Instanz, um direkt mit Paaren zu arbeiten.
Eigentlich ist das als eine Instanz der Funktorklasse nützlich. Zum Beispiel kann ich einen Baum als 'type Tree a = Free T2 a' definieren. In der Tat beinhalten die meisten Anwendungen dieses Typs (in seiner Eigenschaft als Funktor) eine Verzweigung oder Nebenläufigkeit irgendeiner Art. –
Es ist erwähnenswert, dass Sie 'Control.Lens' verwenden können, wenn Sie angeben möchten, welcher Teil des Tupels zu mappen ist. Ein 'Setter' ist wie eine'Functor'-Instanz, die Sie explizit angeben, also' over_1 (+1) (5,3) '==>' (6,3) '; 'über _2 (* 2) (" witzig, 2) '==>' ("witzig", 4) ';" über beide Längen ("hi", "dort") '==>' (2,5) ';' über (both._1) (* 10) ((1,2), (3,4)) '==>' ((10,2), (30,4)) '. – shachaf
danke @shafaf , das ist ein hilfreicher Kommentar. –