Wenn Sie die Implementierungsdetails für einen Moment beiseite legen, ist map
andThen
für Funktionen (unter der funktor-Instanz für A => ?
), und das macht nicht wirklich viel Sinn Sprechen Sie darüber, einander vorzuziehen, wenn wir über Funktionen sprechen und nicht über eine höhere Abstraktionsebene.
Welche Methoden wie map
(und type classes wie Functor
allgemeiner) uns erlauben, ist abstrakt über spezifische Typen oder Typkonstruktoren. Angenommen, wir möchten eine incrementResult
-Methode schreiben, die beispielsweise auf A => Int
oder Kleisli[Option, A, Int]
wirkt. Diese Typen haben nichts gemeinsam in Bezug auf die Vererbung (kurz von AnyRef
, was nutzlos ist), aber A => ?
und Kleisli[Option, A, ?]
sind beide Funktoren, also könnten wir dies schreiben:
Und dann benutze es so (beachte, dass ich kind-projektor verwende, um die Typensyntax etwas zu vereinfachen) ):
%Vor% In diesem Fall gibt es speziell bessere Möglichkeiten, diese Operation zu implementieren, aber es zeigt die allgemeine Idee - wir könnten keine einzige Methode schreiben, die sowohl für normale Funktionen als auch für Kleisli-Pfeile mit andThen
funktioniert, aber wir können mit der zusätzliches Abstraktionsniveau, das map
uns gibt.
Um Ihre Frage zu beantworten, verwenden Sie map
, wenn Sie über alle Typkonstruktoren abstrahieren möchten, die eine Funktorinstanz haben. Wenn Sie jedoch speziell mit Funktionen arbeiten, ist map
andThen
, und - solange wir noch Implementierungsdetails beiseite legen - ist es egal, welche Sie wählen.
Fußnote: das map
, das Scalaz syntax
-Paket Ihnen für Werte von Typen zur Verfügung stellt, die Funktorinstanzen haben, wird als eine Verlängerungsmethode implementiert, so dass ein kleines bisschen Overhead (sowohl zur Kompilierungszeit als auch zur Laufzeit) verwendet wird map
anstelle von andThen
für eine Funktion. Wenn Sie nur mit Funktionen arbeiten und die zusätzliche Abstraktion nicht benötigen, können Sie auch mit andThen
gehen.