I problemi provengono da val p = a*b
Se si scrive il semplice
per (a < - destro (4) .right; b < - Destro (5) .right) cedere a * b
esso compila e ottieni il risultato corretto.
Il vostro problema ha due cause
In primo luogo, le proiezioni Either
map
e flatMap
non hanno la firma al solito, vale a dire per le routine mappa e flatMap definiti in una classe generica M[A]
, (A => B) => M[B]
e (A => M[B]) => M[B]
. Il M[A]
la routine sono definiti in è Either[A,B].RightProjection
, ma in risultati e argomento, abbiamo Either[A,B]
e non la proiezione.
In secondo luogo, il modo val p = a*b
in per la comprensione è tradotto. Scala riferimento, 6,19 p 90:
Un generatore p < - e seguito da un valore definizione p '= e' è tradotto al seguente generatore di coppie di valori, dove x e x 'sono nomi freschi :
(p,p′) <- for([email protected]<-e) yield {val x′@p′ = e′; (x,x′)}
Diamo semplificare il codice solo un po ', lasciando cadere il a <-
. Inoltre, b
e p
rinominati in p
e pp
per essere più vicini alla regola di riscrittura, con pp
per p'
. a
doveva essere portata per (p < - Destro (5) .right; val pp = a * p) resa pp
seguendo la regola, dobbiamo sostituire il generatore + definizione. Cosa c'è intorno a questo, for(
e )yield pp
, invariato.
for((p, pp) <- for([email protected] <- Right(5).right) yield{val [email protected] = a*p; (x,xx)}) yield pp
L'interno per viene riscritto per una semplice mappa
for((p, pp) <- Right(5).right.map{case [email protected] => val [email protected] = a*p; (x,xx)}) yield pp
qui è il problema. Il Right(5).right.map(...)
è di tipo Either[Nothing, (Int,Int)]
, non Either.RightProjection[Nothing, (Int,Int)]
come vorremmo. Non funziona in esterno per (che converte anche in map
.Non esiste il metodo map
su Either
, è definito solo sulle proiezioni.
Se si guarda da vicino il vostro messaggio di errore, si dice così, anche se si parla Product
e Serializable
, si dice che si tratta di un Either[Nothing, (Int, Int)]
, e che nessuna mappa è definita su di esso. La coppia (Int, Int)
proviene direttamente dalla regola di riscrittura.
Per la comprensione è destinato a funzionare bene nel rispetto della firma appropriata. Con il trucco con le proiezioni Either
(che ha anche i suoi vantaggi), abbiamo questo problema.
Ah, sta iniziando a dare un senso. Hai alcuni errori di battitura che mi hanno fatto inciampare all'inizio (numeri mancanti, errori di tipo sottile, ecc.) Che pulirò a breve. – srparish
Il risultato interessante di quanto sopra è che se avrò tipi monadici coerenti starò bene. Quindi, se mi interessa solo proiezioni giuste, potrei creare un implicito come il seguente che risolve effettivamente il problema: implicit def RightProjection [A, B] (v: O [A, B]): Either.RightProjection [A, B] = v.right – srparish
Ancora una volta, grazie per l'approfondita correzione! Avevo letto il riferimento e non avevo ancora capito cosa stava succedendo. Ovviamente in questo semplice esempio, un * b può essere spostato al rendimento, ma se questo è sostituito da un calcolo complesso che deve essere passato a una funzione che restituisce un altro E (ripeti questo più volte), essendo in grado di usare un intermedio l'assegnazione del valore può essere molto più pulita, quindi è necessario avere più livelli di dichiarazioni concatenate/rendimento. – srparish