EitherT[Future, A, B]のUtil
import cats.data.EitherT | |
import cats.implicits._ | |
import scala.collection.immutable.Iterable | |
import scala.concurrent.{ExecutionContext, Future} | |
object EitherTFutureUtils { | |
def eitherT[A, B](a: A): EitherT[Future, B, A] = EitherT(Future.successful(Either.right[B, A](a))) | |
def futureReduceLeft[A, B](xs: Iterable[EitherT[Future, B, A]])(f: (A, A) => A)(implicit ec: ExecutionContext): EitherT[Future, B, A] = { | |
val result = Future.reduceLeft(xs.map(_.value)) { case (orig, x) => | |
for { | |
a <- orig | |
b <- x | |
} yield f(a, b) | |
} | |
EitherT(result) | |
} | |
def sequence[A, B](xs: Iterable[EitherT[Future, B, A]])(implicit ec: ExecutionContext): EitherT[Future, B, List[A]] = { | |
val future = Future.sequence(xs.map(_.value)).map { | |
_.foldLeft[Either[B, List[A]]](Right(Nil)) { | |
case (Left(b), _) => Left(b) | |
case (Right(_), Left(b)) => Left(b) | |
case (Right(list), Right(a)) => Right(a :: list) | |
}.map(_.reverse) | |
} | |
EitherT(future) | |
} | |
} |
This comment has been minimized.
This comment has been minimized.
あとの2つも、Traverse利用すれば簡単になります。 import cats._
def futureReduceLeft[T[_]: Traverse, A: Monoid, B](xs: T[EitherT[Future, B, A]])(implicit ec: ExecutionContext): EitherT[Future, B, A] = xs.sequence.map(_.fold)
def sequence[T[_]: Traverse, A, B](xs: T[EitherT[Future, B, A]])(implicit ec: ExecutionContext): EitherT[Future, B, T[A]] = xs.sequence |
This comment has been minimized.
This comment has been minimized.
よく考えたら、futureReduceLeftの実装でTraverse#sequenceは不要でした。foldだけで実装できますね。 import cats._
import cats.instances.all._
def futureReduceLeft[T[_]: Foldable, A: Monoid, B](xs: T[EitherT[Future, B, A]])(implicit ec: ExecutionContext): EitherT[Future, B, A] = xs.fold
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
やりたいことはrightT使えばもっと簡単に書けますよ。
Applicative[Future]の導出に、暗黙のExecutionContextが必要なことに注意。
もし仮に書き換えるならば: