2016-02-01 8 views
13

Angenommen, ich Daten von 2 Remote-Dienste aggregieren möchten, und Reaktion dienen, so schnell wie ich kann:Monaden VS Applicative functors für Futures

def loadUser: Future[User] 
def loadData: Future[Data] 

case class Payload(user: User, data: Data) 

Ich verstehe, dass dies eine der Reihe nach async Aufgaben ausführt:

for { 
    user <- loadUser 
    data <- loadData 
} yield Payload(user,data) 

Während diese man sie parallel ausführt, weil async Aufgaben bevor sequentiell wobei chaine ausgelöst werden d:

val userF = loadUser 
val dataF = loadData 
for { 
    user <- userF 
    data <- dataF 
} yield Payload(user,data) 

Der Unterschied ist jedoch ein bisschen zu implizit für mich und jemand kann es nicht auf den ersten bemerken.


applicatives löst auch das Job

(loadUser |@| loadData) { Payload(_,_) } 

Kann mir jemand sagen, was ich eher zwischen applicatives und Monaden verwenden würde parallel async Berechnung durchführen? Was sind die Vor- und Nachteile jedes Ansatzes?

+2

Ich denke, dass grundsätzlich, wenn Sie die Ausgabe von etwasComputationA benötigen, um die Ausgabe von etwasComputationB zu berechnen, benutzen Sie eine Monade. Wenn Sie nur zwei verschiedene Dinge berechnen und kombinieren wollen, ist die Anwendung sinnvoll. Während dies bei Anwendungen nicht speziell parallel ist, würde ich argumentieren, dass Monaden aus den oben genannten Gründen inhärent sequenziell sind. Wenn Sie wirklich parallele Berechnungen benötigen, sind Monaden wahrscheinlich nicht die Struktur, nach der Sie suchen. * Wellenhände * – melps

+5

Meine Antwort [hier] (http://stackoverflow.com/a/19881777/334519) hat einige relevante Diskussion. –

+0

Standardsprache für 'Future' Berechnungen parallel ist' zip': 'für ((Benutzer, Daten) <- LoadUser Zip LoadData) Ausbeute Payload (Benutzer, Daten)' – Kolmar

Antwort

12

Also beantworte ich meine eigene Frage, weil alle Kommentare auf nützliche Ressourcen verweisen.

Travis Brown hatte eine schöne answer:

es ist nur eine solide Entwicklung der Praxis die schwächste Abstraktion zu verwenden, die die Arbeit erledigt wird erhalten. Im Prinzip kann dies Optimierungen ermöglichen, die sonst nicht möglich wären, aber was noch wichtiger ist, macht den Code, den wir schreiben, wiederverwendbar.

Auch weist er eine interessante Tatsache aus:

Es ist eine Schande, dass sowohl Haskell und Scala derzeit mit Monaden machen die Arbeit so viel bequemer (syntaktisch, etc.) als mit applicative functors Arbeits

Kolmar darauf hingewiesen, dass es möglich ist, 2-Futures zip:

for ((user, data) <- loadUser zip loadData) yield Payload(user, data) 

Es scheint jedoch, dass zipping more than 2 futures nicht so elegant ist.

So scheint es, dass Applicative Funktors am besten für den Job geeignet ist, aber die Scala standart Bibliothek nicht ermutigt uns sehr, sie zu Monade im Vergleich zu verwenden, und Sie benötigen eine zusätzliche Bibliothek wie Scalaz oder Katzen