genkai.monad.FutureMonadAsyncError.scala Maven / Gradle / Ivy
package genkai.monad
import scala.util.{Failure, Success, Try}
import scala.concurrent.{ExecutionContext, Future, Promise}
class FutureMonadAsyncError(implicit ec: ExecutionContext) extends MonadAsyncError[Future] {
override def pure[A](value: A): Future[A] = Future.successful(value)
override def map[A, B](fa: => Future[A])(f: A => B): Future[B] = fa.map(f)
override def flatMap[A, B](fa: => Future[A])(f: A => Future[B]): Future[B] = fa.flatMap(f)
override def tap[A, B](fa: => Future[A])(f: A => Future[B]): Future[A] =
fa.flatMap(r => f(r).map(_ => r))
override def raiseError[A](error: Throwable): Future[A] = Future.failed(error)
override def adaptError[A](
fa: => Future[A]
)(pf: PartialFunction[Throwable, Throwable]): Future[A] =
fa.transformWith {
case Failure(exception) if pf.isDefinedAt(exception) => raiseError(pf(exception))
case _ => fa
}
override def mapError[A](fa: => Future[A])(f: Throwable => Throwable): Future[A] =
fa.transformWith {
case Failure(exception) => raiseError(f(exception))
case _ => fa
}
override def handleError[A](fa: => Future[A])(pf: PartialFunction[Throwable, A]): Future[A] =
fa.recover(pf)
override def handleErrorWith[A](fa: => Future[A])(
pf: PartialFunction[Throwable, Future[A]]
): Future[A] =
fa.recoverWith(pf)
override def ifM[A](
fcond: => Future[Boolean]
)(ifTrue: => Future[A], ifFalse: => Future[A]): Future[A] =
fcond.flatMap { flag =>
if (flag) ifTrue
else ifFalse
}
override def whenA[A](cond: Boolean)(f: => Future[A]): Future[Unit] =
if (cond) f.map(_ => ())
else unit
override def void[A](fa: => Future[A]): Future[Unit] = fa.map(_ => ())
override def eval[A](f: => A): Future[A] = Future(f)
override def async[A](k: (Either[Throwable, A] => Unit) => Unit): Future[A] = {
val p = Promise[A]()
k {
case Left(value) => p.failure(value)
case Right(value) => p.success(value)
}
p.future
}
// ignore cancel logic
override def cancelable[A](k: (Either[Throwable, A] => Unit) => () => Future[Unit]): Future[A] = {
val p = Promise[A]()
k {
case Left(value) => p.failure(value)
case Right(value) => p.success(value)
}
p.future
}
override def guarantee[A](f: => Future[A])(g: => Future[Unit]): Future[A] = {
val p = Promise[A]()
suspend(f).onComplete {
case Failure(exception) =>
suspend(g).flatMap(_ => Future.failed(exception)).onComplete(r => p.complete(r))
case Success(value) => suspend(g).map(_ => value).onComplete(r => p.complete(r))
}
p.future
}
override def bracket[A, B](acquire: => Future[A])(use: A => Future[B])(
release: A => Future[Unit]
): Future[B] = {
val p = Promise[B]()
suspend(acquire).onComplete {
case Failure(exception) => p.failure(exception)
case Success(resource) =>
suspend(use(resource)).onComplete {
case Failure(exception) =>
suspend(release(resource)).flatMap(_ => raiseError(exception)).onComplete(p.complete)
case Success(result) => suspend(release(resource)).map(_ => result).onComplete(p.complete)
}
}
p.future
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy