Created
July 11, 2019 09:14
-
-
Save ponkotuy/4c67ed1d3857ce06548236675cc5a721 to your computer and use it in GitHub Desktop.
EitherT[Future, A, B]のUtil
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
あとの2つも、Traverse利用すれば簡単になります。
(とはいえ元のIterableの例よりも制約が厳しくなってしまってるので、ここがIterableである必要があるならば別の方法が要りますね…)
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
よく考えたら、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
Monoid[A]
から Monoid[EitherT[Future, B, A]]
を導出できるのが理由です。以下参照。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
やりたいことはrightT使えばもっと簡単に書けますよ。
Applicative[Future]の導出に、暗黙のExecutionContextが必要なことに注意。
もし仮に書き換えるならば: