Skip to content

Instantly share code, notes, and snippets.

@chenharryhua
Created March 14, 2015 01:50
Show Gist options
  • Save chenharryhua/0d914addaaf32dabdf42 to your computer and use it in GitHub Desktop.
Save chenharryhua/0d914addaaf32dabdf42 to your computer and use it in GitHub Desktop.
package futurable
import scala.concurrent.Future
import concurrent.ExecutionContext.Implicits.global
trait Futurable[In] {
type Out
def apply(in: In): Future[Out]
}
case object NoneException extends Exception
trait LowerPriorityFuturableOption {
implicit def futureOption[T] = new Futurable[Option[T]] {
type Out = T
def apply(in: Option[T]): Future[T] = {
in match {
case None => Future.failed(NoneException)
case Some(x) => Future.successful(x)
}
}
}
}
trait FuturableOption extends LowerPriorityFuturableOption {
implicit def futureOption2[T](implicit fo: Futurable[Option[T]]) =
new Futurable[Option[Option[T]]] {
type Out = fo.Out
def apply(in: Option[Option[T]]) = fo(in.flatten)
}
}
trait LowerPriorityFuturableFuture {
implicit def futureFuture[T] = new Futurable[Future[T]] {
type Out = T
def apply(in: Future[T]): Future[T] = in
}
}
trait FuturableFuture extends LowerPriorityFuturableFuture {
implicit def futureFuture2[T](implicit fuf: Futurable[Future[T]]) =
new Futurable[Future[Future[T]]] {
type Out = fuf.Out
def apply(in: Future[Future[T]]) = fuf(for { f2 <- in; f <- f2 } yield f)
}
}
object Futurable
extends FuturableOption
with FuturableFuture {
implicit def futureOptionIso[T](implicit fo: Futurable[Option[T]]) =
new Futurable[Future[Option[T]]] {
type Out = fo.Out
def apply(in: Future[Option[T]]) = in.flatMap { x => fo(x) }
}
implicit def optionFutureIso[T](implicit fuf: Futurable[Future[T]]) =
new Futurable[Option[Future[T]]] {
type Out = fuf.Out
def apply(in: Option[Future[T]]) = {
val f = in match {
case Some(x) => x
case None => Future.failed(NoneException)
}
fuf(f)
}
}
}
object FuturableSyntax {
implicit class FOSyntax[T, O](a: T)(implicit val f: Futurable[T] { type Out = O }) {
def toFuture = f(a)
}
}
object MyTest {
import FuturableSyntax._
val oooo: Option[Option[Option[Option[Int]]]] = ???
val ooooi: Future[Int] = oooo.toFuture
val ffff: Future[Future[Future[Future[Int]]]] = ???
val ffffi: Future[Int] = ffff.toFuture
val ooofff: Option[Option[Option[Future[Future[Future[Int]]]]]] = ???
val ooofffi: Future[Int] = ooofff.toFuture
val fffooo: Future[Future[Future[Option[Option[Option[Int]]]]]] = ???
val fffoooi: Future[Int] = fffooo.toFuture
val ofooffo: Option[Future[Option[Option[Future[Future[Option[Int]]]]]]] = ???
val ofooffoi: Future[Int] = ofooffo.toFuture
val ofoofooof: Option[Future[Option[Option[Future[Option[Option[Option[Future[Int]]]]]]]]] = ???
val ofoofooofi: Future[Int] = ofoofooof.toFuture
val foffofffo: Future[Option[Future[Future[Option[Future[Future[Future[Option[Int]]]]]]]]] = ???
val foffofffoi: Future[Int] = foffofffo.toFuture
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment