Skip to content

Instantly share code, notes, and snippets.

@pbassiner
Last active April 19, 2017 20:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pbassiner/6bb41c132da822cce2020827d6163cc9 to your computer and use it in GitHub Desktop.
Save pbassiner/6bb41c132da822cce2020827d6163cc9 to your computer and use it in GitHub Desktop.
Blog Post - Composing Future. List and Either: code snippets
def getCommitsWithAuthor(): Future[Either[Error, List[CommitAndAuthor]]] = ???
/**
* Transformer for `Either`, allowing the effect of an arbitrary type constructor `F` to be combined with the
* fail-fast effect of `Either`.
*
* `EitherT[F, A, B]` wraps a value of type `F[Either[A, B]]`. An `F[C]` can be lifted in to `EitherT[F, A, C]` via `EitherT.right`,
* and lifted in to a `EitherT[F, C, B]` via `EitherT.left`.
*/
final case class EitherT[F[_], A, B](value: F[Either[A, B]]) {
...
}
def getCommitsWithAuthor(): Future[Either[Error, List[CommitAndAuthor]]] =
getCommits() flatMap {
case Right(commits) => sequence(listCommitsAndAuthor(commits)) map { list =>
list.foldLeft(
Right[Error, List[CommitAndAuthor]](List.empty).asInstanceOf[Either[Error, List[CommitAndAuthor]]]
)(
(acc, x) => x match {
case Right(value) => acc.map(list => list :+ value)
case Left(err) => acc.left.map(_ => err)
}
)
}
case Left(e) => Future.successful(Left(e))
}
def getCommitsWithAuthor(): Future[Either[Error, List[CommitAndAuthor]]] =
getCommits() flatMap {
case Right(commits) => sequence(
commits =>
commits map { commit =>
getAuthor(commit.id) map { either =>
either map { author =>
CommitAndAuthor(commit, author)
}
}
}
) map { list =>
list.foldLeft(
Right[Error, List[CommitAndAuthor]](List.empty).asInstanceOf[Either[Error, List[CommitAndAuthor]]]
)(
(acc, x) => x match {
case Right(value) => acc.map(list => list :+ value)
case Left(err) => acc.left.map(_ => err)
}
)
}
case Left(e) => Future.successful(Left(e))
}
sequence(listCommitsAndAuthor(commits)) map { list =>
list.foldLeft(
Right[Error, List[CommitAndAuthor]](List.empty).asInstanceOf[Either[Error, List[CommitAndAuthor]]]
)(
(acc, x) => x match {
case Right(value) => acc.map(list => list :+ value)
case Left(err) => acc.left.map(_ => err)
}
)
}
def listCommitsAndAuthor: List[Commit] => List[Future[Either[Error, CommitAndAuthor]]] =
commits =>
commits map { commit =>
getAuthor(commit.id) map { either =>
either map { author =>
CommitAndAuthor(commit, author)
}
}
}
sequence(listCommitsAndAuthor(commits))
def getCommits(): Future[Either[Error, List[Commit]]]
def getAuthor(commitId: String): Future[Either[Error, Author]]
final case class Commit(id: String)
final case class Author(id: String)
final case class CommitAndAuthor(commit: Commit, author: Author)
import cats.data.EitherT
import cats.instances.future._
import cats.instances.list._
import cats.syntax.traverse._
def getCommitsWithAuthor(): Future[Either[Error, List[CommitAndAuthor]]] =
(for {
commits <- EitherT(getCommits())
result <- commits.map { commit =>
EitherT(getAuthor(commit.id)) map { author => CommitAndAuthor(commit, author) }
}.sequenceU
} yield result).value
import cats.data.EitherT
import cats.instances.future._
implicit val ec: ExecutionContext = scala.concurrent.ExecutionContext.Implicits.global
commits.map { commit =>
EitherT(getAuthor(commit.id)) map { author => CommitAndAuthor(commit, author) }
}
import cats.data.EitherT
import cats.instances.list._
import cats.instances.future._
import cats.syntax.traverse._
implicit val ec: ExecutionContext = scala.concurrent.ExecutionContext.Implicits.global
commits.map { commit =>
EitherT(getAuthor(commit.id)) map { author => CommitAndAuthor(commit, author) }
}.sequenceU
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment