Created
March 20, 2015 10:50
-
-
Save chenharryhua/cceff7792875dd9009ec to your computer and use it in GitHub Desktop.
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
package futurable | |
import scala.concurrent.ExecutionContext | |
import scala.concurrent.Future | |
import scala.language.{ higherKinds, implicitConversions } | |
import scala.util.Try | |
import scalaz._ | |
import Scalaz._ | |
object Futurable5 { | |
trait FutureLike[In] { | |
type Out | |
def apply(in: In)(implicit ec: ExecutionContext): Future[Out] | |
} | |
case object NoneException extends Exception | |
trait RebuildException[E <: Throwable] { | |
def apply(t: Throwable): E | |
} | |
object RebuildException { | |
implicit def noneException = new RebuildException[NoneException.type] { | |
def apply(t: Throwable) = NoneException | |
} | |
implicit def normalException = new RebuildException[Exception] { | |
def apply(t: Throwable) = new Exception(t.getMessage) | |
} | |
} | |
trait LowPriorityFutureLike { | |
implicit def futureInstance[T] = new FutureLike[Future[T]] { | |
type Out = T | |
def apply(in: Future[T])(implicit ec: ExecutionContext): Future[T] = in | |
} | |
implicit def eitherInstance[E <: Throwable, T] = | |
new FutureLike[Either[E, T]] { | |
type Out = T | |
def apply(in: Either[E, T])(implicit ec: ExecutionContext): Future[T] = | |
in match { | |
case Right(x) => Future.successful(x) | |
case Left(y) => Future.failed(y) | |
} | |
} | |
implicit def tryInstance[T] = new FutureLike[Try[T]] { | |
type Out = T | |
def apply(in: Try[T])(implicit ec: ExecutionContext): Future[T] = | |
in match { | |
case util.Success(x) => Future.successful(x) | |
case util.Failure(y) => Future.failed(y) | |
} | |
} | |
implicit def optionInstance[T] = new FutureLike[Option[T]] { | |
type Out = T | |
def apply(in: Option[T])(implicit ec: ExecutionContext): Future[T] = | |
in match { | |
case None => Future.failed(NoneException) | |
case Some(x) => Future.successful(x) | |
} | |
} | |
} | |
trait FutureLikeRec extends LowPriorityFutureLike { | |
type FF[X] = Future[Future[X]] | |
implicit def futureInstanceRec[T](implicit fk: FutureLike[Future[T]]) = | |
new FutureLike[FF[T]] { | |
type Out = fk.Out | |
def apply(in: FF[T])(implicit ec: ExecutionContext): Future[Out] = | |
in.flatMap { x => fk(x) } | |
} | |
type EE[E <: Throwable, X] = Either[E, Either[E, X]] | |
implicit def eitherInstanceRec[E <: Throwable, T]( | |
implicit fk: FutureLike[Either[E, T]]) = | |
new FutureLike[EE[E, T]] { | |
type Out = fk.Out | |
def apply(in: EE[E, T])(implicit ec: ExecutionContext): Future[Out] = { | |
val cont = in.fold(a => Left(a), identity) | |
fk(cont) | |
} | |
} | |
type TT[X] = Try[Try[X]] | |
implicit def tryInstanceRec[T](implicit fk: FutureLike[Try[T]]) = | |
new FutureLike[TT[T]] { | |
type Out = fk.Out | |
def apply(in: TT[T])(implicit ec: ExecutionContext): Future[Out] = | |
fk(for { tt <- in; t <- tt } yield t) | |
} | |
type OO[X] = Option[Option[X]] | |
implicit def optionInstanceRec[T](implicit fk: FutureLike[Option[T]]) = | |
new FutureLike[OO[T]] { | |
type Out = fk.Out | |
def apply(in: OO[T])(implicit ec: ExecutionContext): Future[Out] = | |
fk(for { oo <- in; o <- oo } yield o) | |
} | |
} | |
trait OptionFutureIso extends FutureLikeRec { | |
type FO[X] = Future[Option[X]] | |
implicit def foInstance[T](implicit fk: FutureLike[Option[T]]) = | |
new FutureLike[FO[T]] { | |
type Out = fk.Out | |
def apply(in: FO[T])(implicit ec: ExecutionContext): Future[Out] = | |
in.flatMap { x => fk(x) } | |
} | |
type OF[X] = Option[Future[X]] | |
implicit def ofInstance[T](implicit fk: FutureLike[Future[T]]) = | |
new FutureLike[OF[T]] { | |
type Out = fk.Out | |
def apply(in: OF[T])(implicit ec: ExecutionContext): Future[Out] = { | |
val f0: Future[T] = in match { | |
case Some(x) => x | |
case None => Future.failed(NoneException) | |
} | |
fk(f0) | |
} | |
} | |
} | |
trait TryFutureIso extends FutureLikeRec { | |
type FT[X] = Future[Try[X]] | |
implicit def ftIntance[T](implicit fk: FutureLike[Try[T]]) = | |
new FutureLike[FT[T]] { | |
type Out = fk.Out | |
def apply(in: FT[T])(implicit ec: ExecutionContext): Future[Out] = | |
in.flatMap { x => fk(x) } | |
} | |
type TF[X] = Try[Future[X]] | |
implicit def tfInstance[T](implicit fk: FutureLike[Future[T]]) = | |
new FutureLike[TF[T]] { | |
type Out = fk.Out | |
def apply(in: TF[T])(implicit ec: ExecutionContext): Future[Out] = { | |
val f0: Future[Future[T]] = in match { | |
case util.Success(x) => Future.successful(x) | |
case util.Failure(y) => Future.failed(y) | |
} | |
f0.flatMap { x => fk(x) } | |
} | |
} | |
} | |
trait EitherFutureIso extends FutureLikeRec { | |
type FE[E <: Throwable, X] = Future[Either[E, X]] | |
implicit def feIntance[E <: Throwable, T](implicit fk: FutureLike[Either[E, T]]) = | |
new FutureLike[FE[E, T]] { | |
type Out = fk.Out | |
def apply(in: FE[E, T])(implicit ec: ExecutionContext): Future[Out] = | |
in.flatMap { x => fk(x) } | |
} | |
type EF[E <: Throwable, X] = Either[E, Future[X]] | |
implicit def efInstance[E <: Throwable, T](implicit fk: FutureLike[Future[T]]) = | |
new FutureLike[EF[E, T]] { | |
type Out = fk.Out | |
def apply(in: EF[E, T])(implicit ec: ExecutionContext): Future[Out] = { | |
val f0: Future[Future[T]] = in match { | |
case Right(x) => Future.successful(x) | |
case Left(y) => Future.failed(y) | |
} | |
f0.flatMap { x => fk(x) } | |
} | |
} | |
} | |
trait TryEitherIso extends FutureLikeRec { | |
type ET[E <: Throwable, X] = Either[E, Try[X]] | |
implicit def etIntance[E <: Throwable, T](implicit fk: FutureLike[Try[T]]) = | |
new FutureLike[ET[E, T]] { | |
type Out = fk.Out | |
def apply(in: ET[E, T])(implicit ec: ExecutionContext): Future[Out] = | |
in match { | |
case Right(x) => fk(x) | |
case Left(y) => fk(util.Failure(y)) | |
} | |
} | |
type TE[E <: Throwable, X] = Try[Either[E, X]] | |
implicit def teInstance[E <: Throwable, T]( | |
implicit fk: FutureLike[Either[E, T]], re: RebuildException[E]) = | |
new FutureLike[TE[E, T]] { | |
type Out = fk.Out | |
def apply(in: TE[E, T])(implicit ec: ExecutionContext): Future[Out] = | |
in match { | |
case util.Success(x) => fk(x) | |
case util.Failure(y) => fk(Left(re(y))) | |
} | |
} | |
} | |
trait TryOptionIso extends FutureLikeRec { | |
type OT[X] = Option[Try[X]] | |
implicit def otIntance[T](implicit fk: FutureLike[Try[T]]) = | |
new FutureLike[OT[T]] { | |
type Out = fk.Out | |
def apply(in: OT[T])(implicit ec: ExecutionContext): Future[Out] = | |
in match { | |
case None => fk(util.Failure(NoneException)) | |
case Some(x) => fk(x) | |
} | |
} | |
type TO[X] = Try[Option[X]] | |
implicit def toInstance[T](implicit fk: FutureLike[Option[T]]) = | |
new FutureLike[TO[T]] { | |
type Out = fk.Out | |
def apply(in: TO[T])(implicit ec: ExecutionContext): Future[Out] = | |
in match { | |
case util.Success(x) => fk(x) | |
case util.Failure(y) => fk(None) | |
} | |
} | |
} | |
trait EitherOptionIso extends FutureLikeRec { | |
type OE[E <: Throwable, X] = Option[Either[E, X]] | |
implicit def oeIntance[E <: Throwable, T]( | |
implicit fk: FutureLike[Either[E, T]], re: RebuildException[E]) = | |
new FutureLike[OE[E, T]] { | |
type Out = fk.Out | |
def apply(in: OE[E, T])(implicit ec: ExecutionContext): Future[Out] = | |
in match { | |
case None => fk(Left(re(NoneException))) | |
case Some(x) => fk(x) | |
} | |
} | |
type EO[E <: Throwable, X] = Either[E, Option[X]] | |
implicit def eoInstance[E <: Throwable, T](implicit fk: FutureLike[Option[T]]) = | |
new FutureLike[EO[E, T]] { | |
type Out = fk.Out | |
def apply(in: EO[E, T])(implicit ec: ExecutionContext): Future[Out] = | |
in match { | |
case Right(x) => fk(x) | |
case Left(y) => fk(None) | |
} | |
} | |
} | |
object FutureLike extends FutureLikeRec | |
with OptionFutureIso | |
with EitherFutureIso | |
with TryFutureIso | |
with TryEitherIso | |
with TryOptionIso | |
with EitherOptionIso { | |
implicit def eitherTransformer[F[_]: Monad, E <: Throwable, T](implicit fl: FutureLike[F[Future[T]]]) = | |
new FutureLike[EitherT[F, E, T]] { | |
type Out = fl.Out | |
def apply(in: EitherT[F, E, T])(implicit ec: ExecutionContext): Future[Out] = { | |
val cont = in.run.map { | |
case \/-(x) => Future.successful(x) | |
case -\/(y) => Future.failed(y) | |
} | |
fl(cont) | |
} | |
} | |
implicit def optionTransformer[F[_]: Monad, T](implicit fo: FutureLike[F[Future[T]]]) = | |
new FutureLike[OptionT[F, T]] { | |
type Out = fo.Out | |
def apply(in: OptionT[F, T])(implicit ec: ExecutionContext): Future[Out] = { | |
val cont = in.run.map { | |
case None => Future.failed(NoneException) | |
case Some(x) => Future.successful(x) | |
} | |
fo(cont) | |
} | |
} | |
} | |
object FuturableSyntax { | |
implicit class FSyntax[F, O](a: F)(implicit val f: FutureLike[F] { type Out = O }) { | |
def toFuture(implicit ec: ExecutionContext) = f(a) | |
} | |
} | |
object MyTest { | |
import FuturableSyntax._ | |
import scala.concurrent.ExecutionContext.Implicits.global | |
val ooo: Option[Option[Option[Int]]] = ??? | |
val oooi: Future[Int] = ooo.toFuture | |
val fff: Future[Future[Future[Int]]] = ??? | |
val fffi: Future[Int] = fff.toFuture | |
val eee: Either[Exception, Either[Exception, Either[Exception, Int]]] = ??? | |
// val eeei: Future[Int] = eee.toFuture | |
val ttt: Try[Try[Try[Int]]] = ??? | |
val ttti: Future[Int] = ttt.toFuture | |
val ggg = ttt.toFuture | |
val e: Either[Exception, Int] = ??? | |
val en = e.toFuture | |
val ofoofooof: Option[Future[Option[Option[Future[Option[Option[Option[Future[Int]]]]]]]]] = ??? | |
val ofoofooofi: Future[Int] = ofoofooof.toFuture | |
val ofoofooofn = ofoofooof.toFuture | |
val tfttftttf: Try[Future[Try[Try[Future[Try[Try[Try[Future[Int]]]]]]]]] = ??? | |
val tfttftttfi: Future[Int] = tfttftttf.toFuture | |
val efeef: Either[Exception, Future[Either[Exception, Either[Exception, Future[Int]]]]] = ??? | |
val efeefi: Future[Int] = efeef.toFuture | |
val etet: Either[Exception, Try[Either[Exception, Try[Int]]]] = ??? | |
val eteti: Future[Int] = etet.toFuture | |
val ftf: Future[Try[Future[Int]]] = ??? | |
val ftfi: Future[Int] = ftf.toFuture | |
val otf: Option[Try[Future[Int]]] = ??? | |
val otfi: Future[Int] = otf.toFuture | |
val ot: Option[Try[Int]] = ??? | |
val oti: Future[Int] = ot.toFuture | |
val to: Try[Option[Int]] = ??? | |
val toi: Future[Int] = to.toFuture | |
val otootfooettf: Option[Try[Option[Option[Try[Future[Option[Option[Option[Either[Exception, Try[Try[Future[Int]]]]]]]]]]]]] = ??? | |
val otootfooottfi: Future[Int] = otootfooettf.toFuture | |
val etfo: Option[Either[Exception, Try[Future[Option[Either[Exception, Future[Try[Int]]]]]]]] = ??? | |
val etfoi: Future[Int] = etfo.toFuture | |
val et: EitherT[Future, Exception, Int] = ??? | |
val etf: Future[Int] = et.toFuture | |
val fEto: Future[EitherT[Option, Exception, Int]] = ??? | |
val fEtof = fEto.toFuture | |
val oT: OptionT[Future, Int] = ??? | |
val oTf = oT.toFuture | |
// val a: Option[OptionT[Try, Exception, Int]] = ??? | |
// val aa = a.toFuture | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment