2016-02-01 20 views
13

Supponiamo che io voglio aggregare i dati da 2 servizi remoti, e servono la risposta più veloce che posso:funtori Monadi VS applicative per Futures

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

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

Capisco che questo esegue compiti asincroni in sequenza:

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

mentre questo li esegue in parallelo, perché le attività asincrone vengono attivati ​​prima di essere in sequenza chaine d:

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

La differenza è comunque un po 'troppo implicita per me e qualcuno potrebbe non notarlo all'inizio.


applicativi risolve anche il lavoro

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

Qualcuno può dirmi quello che io preferisco usare tra applicativi e monadi di eseguire in parallelo computazione asincrona? Quali sono i pro e i contro di ciascun approccio?

+2

penso che fondamentalmente se hai bisogno dell'output di someComputationA per calcolare l'output di someComputationB usi una monade. Se vuoi solo calcolare due cose separate e combinarle, lo farà l'applicativo. Sebbene questo non sia niente di specificamente "parallelo" rispetto agli applicativi, direi che, per le ragioni sopra esposte, le monadi sono intrinsecamente sequenziali. Qui, se hai bisogno di calcoli veramente paralleli, le monadi probabilmente non sono la struttura che stai cercando. * waves hands * – melps

+5

La mia risposta [qui] (http://stackoverflow.com/a/19881777/334519) ha alcune discussioni rilevanti. –

+0

L'idioma standard per eseguire calcoli 'Future' in parallelo è' zip': 'for ((utente, dati) <- loadUser zip loadData) yield Payload (utente, dati)' – Kolmar

risposta

12

Quindi, sto rispondendo alla mia stessa domanda perché tutti i commenti collegano a risorse utili.

Travis Brown ha avuto un bel answer:

è solo una pratica di sviluppo solido di utilizzare l'astrazione meno potente che otterrà il lavoro fatto. In linea di principio, ciò potrebbe consentire ottimizzazioni che altrimenti non sarebbero possibili, ma soprattutto rende più riutilizzabile il codice che scriviamo.

anche fa notare un fatto interessante:

E 'un peccato che sia Haskell e Scala attualmente fanno lavorare con monadi in modo molto più conveniente (sintatticamente, etc.) che lavorare con funtori applicative

Kolmar ha sottolineato che è possibile zip 2 Futures:

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

Tuttavia sembra che zipping more than 2 futures non sia così elegante.

così sembra che applicativo funtore è più adatto per il lavoro, ma la biblioteca standart Scala non ci incoraggiano molto a usare loro rispetto al monade, e avete bisogno di una libreria extra come Scalaz o gatti