Как связать будущее [\/[A,B]] в скале?
Как я могу сделать for
понимание с данными типа Future[\/[String,Int]]
Вот отправная точка, которая не компилируется.
import scala.concurrent.{ExecutionContext,future,Future}
import scalaz._
import Scalaz._
import ExecutionContext.Implicits.global
def calculateStuff(i:Int):Future[\/[String,Int]] = future{\/-(i)}
for {
v1Either <- calculateStuff(1)
v1Int <- v1Either
v2Either < calculateStuff(v1Int)
v2Int <- v2Either
v3Either <- calculateStuff(v2Int)
v3Int <- v3Either
} yield {
v1Int + v2Int + v3Int
}
Замечания: calculateStuff
Это всего лишь пример, на самом деле будут разные функции, каждая из которых зависит от результата предыдущего.
1 ответ
Прежде всего я должен отметить, что я предполагаю, что у вас есть веская причина для реализации вашей собственной обработки ошибок (через \/
) вместо использования функциональности, встроенной в Future
Если это так, то, как подсказывает ваш тег, проблема именно этого типа заключается в том, для чего нужны монадные преобразователи - просто оберните ваши вычисления в EitherT
:
import scalaz._, Scalaz._, contrib.std._
import scala.concurrent.{ ExecutionContext, future, Future }
import ExecutionContext.Implicits.global
def calculateStuff(i: Int): EitherT[Future, String, Int] =
EitherT(future(\/-(i)))
val computation = for {
v1Int <- calculateStuff(1)
v2Int <- calculateStuff(v1Int + 1)
v3Int <- calculateStuff(v2Int + 2)
} yield v1Int + v2Int + v3Int
Обратите внимание, что я использую Monad
экземпляр для Future
из библиотеки скаляпа-вкладов Typelevel.
Сейчас computation.run
даст вам Future[String \/ Int]
,
Если вам нужно ввести чистое значение в вычисления, вы можете просто использовать point
и тип лямбда:
v4Int <- 1.point[({ type L[x] = EitherT[Future, String, x] })#L]
Вы также можете определить свой собственный псевдоним типа, чтобы это выглядело немного лучше.
Если вы хотите использовать \/
значение в for
понимание, вы можете просто указать на это Future
и завернуть все это в EitherT
:
v5Int <- EitherT(1.right[String].point[Future])
Также возможно поднять старый добрый Future
в трансформированную монаду с (несколько смущающим именем) liftM
:
v6Int <- future(1).liftM[({ type T[m[+_], a] = EitherT[m, String, a] })#T]
В этом случае вам почти наверняка понадобится псевдоним типа - эта строка в основном шумовая.