2016-07-02 1 views
8

Mit Scalaz kann eine Funktion über eine andere Funktion zugeordnet werden. Wann möchte ich map über andThen verwenden? Gibt es einen klaren Vorteil mit map? DankWenn Karte über eine Funktion nützlich ist, wenn Sie haben und dann

Zum Beispiel

val f: Int => Int = (a) => a + 10 

val g: Int => Int = (a) => a * 100 

(f map g map {_*3})(10) == (f andThen g andThen {_*3})(10) // true 
+0

Nun 'map' funktioniert auf jedem Funktor, nicht nur Funktionen. – Bergi

+0

Ich habe darüber auch nachgedacht. Also kann ich eine Liste von Optionen und Listen von Funktoren abbilden, aber ich konnte mir nicht vorstellen, wie man eine Liste von Funktoren erstellt. – thlim

Antwort

12

Implementierungsdetails für einen Moment Abgesehen, mapistandThen für Funktionen (unter der Funktors Instanz für A => ?), und es ist nicht wirklich viel Sinn machen über die Bevorzugung von einander zu sprechen, wenn wir über Funktionen sprechen und nicht über eine höhere Ebene der Abstraktion.

Welche Methoden wie map (und Typklassen wie Functor allgemeiner) erlauben uns zu tun ist abstrakt über bestimmte Typen oder Typkonstruktoren. Angenommen, wir möchten eine incrementResult-Methode schreiben, die beispielsweise auf A => Int oder Kleisli[Option, A, Int] funktioniert. Diese Typen haben nichts gemeinsam in Bezug auf Vererbung (kurz AnyRef, die nutzlos ist), aber A => ? und Kleisli[Option, A, ?] sind beide functors, so konnten wir dieses schreiben:

import scalaz._, Scalaz._ 

def incrementResult[F[_]: Functor](f: F[Int]): F[Int] = f.map(_ + 1) 

Und es dann wie folgt verwenden (beachten sie, dass ich kind-projector bin mit der Art Syntax ein wenig zu vereinfachen):

scala> val plainOldFuncTriple: Int => Int = _ * 3 
plainOldFuncTriple: Int => Int = <function1> 

scala> val optionKleisliTriple: Kleisli[Option, Int, Int] = Kleisli(i => Some(i * 3)) 
optionKleisliTriple: scalaz.Kleisli[Option,Int,Int] = Kleisli(<function1>) 

scala> val f = incrementResult[Int => ?](plainOldFuncTriple) 
f: Int => Int = <function1> 

scala> val k = incrementResult[Kleisli[Option, Int, ?]](optionKleisliTriple) 
k: scalaz.Kleisli[Option,Int,Int] = Kleisli(<function1>) 

scala> f(10) 
res0: Int = 31 

scala> k(10) 
res1: Option[Int] = Some(31) 

In diesem Fall speziell gibt es bessere Möglichkeiten, um diese Operation zu implementieren, aber es zeigt die allgemeine Idee-wir konnten eine nicht schreiben einzelne Methode, die sowohl für normale Funktionen als auch für Kleisli-Pfeile mitfunktioniert 210, aber wir können mit der zusätzlichen Ebene der Abstraktion, die uns map gibt.

So Ihre Frage ich würde Gebrauch zu beantworten map, wenn Sie über alle Typkonstruktoren abstrahieren wollen, die eine Funktors Instanz haben, aber wenn Sie speziell mit Funktionen arbeiten, mapistandThen und-so lange Da wir immer noch Implementierungsdetails beiseite legen, ist es egal, welche Sie wählen.


Fußnoten: die map die Scalaz der syntax Paket, das Ihnen für die Werte von Arten gibt, die Funktors Instanzen wird als Erweiterung Methode implementiert, so dass es ein klein wenig Overhead (sowohl bei der Kompilierung und Laufzeit) bei der Verwendung von 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 andThen verwenden.

+1

Wir * können * eine einzige Methode schreiben, die sowohl mit als auch mit '' arbeitet '' 'def incrementResult [~> [_, _]: Verfassen, A] (f: A ~> Int): A ~> Int = f undThen (_ + 1) ' –

+1

@ JulienRichard-Foy Sicher (das ist, was ich mit" bessere Möglichkeiten, diese Operation zu implementieren "gemeint habe), aber das ist eine Art Ablenkung, da das' und 'dann' nicht das 'andThen' auf' Function1' ist, was Worum geht es dem OP? –

+0

@ JulienRichard-Foy Wie behebe ich das? 'value andThen ist kein Mitglied von type parameter ~> [A, Int]' – thlim

Verwandte Themen