Skip to content

Instantly share code, notes, and snippets.

@tarsa
Created Apr 19, 2017
Embed
What would you like to do?
Poor man's Future sequencing sugar
package futseq
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
import scala.language.implicitConversions
object FutSeq {
sealed trait HList
sealed trait HCons[H, +T <: HList] extends HList
sealed trait HNil extends HList
sealed class Completer[H <: HList] private (val futures: List[Future[Any]]) {
def apply[T](future: Future[T]): Completer[HCons[future.type, H]] =
new Completer[HCons[future.type, H]](future :: futures)
}
object Completer extends Completer[HNil](Nil) {
implicit def completerToFuture[H <: HList](
completer: Completer[H]): Future[Evidence[H]] =
Future.sequence(completer.futures).map(_ => new Evidence[H])
sealed class Evidence[H <: HList] private[Completer] {
def apply[T](future: Future[T])(implicit check: In[future.type, H]): T =
check(future).value.get.get
}
}
final class In[V, H <: HList] private {
def apply(value: V): V =
value
}
object In {
implicit def inHead[V, H <: HCons[V, HList]]: In[V, H] =
new In[V, H]
implicit def inTail[V, U, T <: HList](
implicit in: In[V, T]): In[V, HCons[U, T]] =
new In[V, HCons[U, T]]
}
}
object Main {
import FutSeq._
def main(args: Array[String]): Unit = {
val x = Future(9)
val result: Future[Int] =
for {
a <- Future(5)
b = Future(8)
c = Future(a + 6)
ev <- Completer(b)(c)
d <- Future(ev(c) - ev(b))
} yield {
a + ev(b) + ev(c) * d // + ev(x) // does not compile, good!
}
println(Await.result(result, Duration.Inf))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment