tofu.syntax.monadError.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tofu-core_2.13 Show documentation
Show all versions of tofu-core_2.13 Show documentation
Opinionated Set of tool for functional programming in scala
package tofu.syntax
import cats.{ApplicativeError, MonadError}
import cats.data.EitherT
import cats.syntax.applicativeError._
import cats.syntax.either._
import cats.syntax.functor._
import either._
object monadError {
implicit class MonadErrorFOps[F[_], A](val fa: F[A]) extends AnyVal {
def retryAttempt[E](count: Int)(implicit F: MonadError[F, E]): F[Either[List[E], A]] =
F.tailRecM((count, List.empty[E])) {
case (cnt, acc) =>
if (cnt <= 0) F.pure(acc.reverse.asLeft.asRight)
else
fa.attempt.map {
case Left(err) => (cnt - 1, err :: acc).asLeft
case Right(v) => v.asRight.asRight
}
}
def retry[E](count: Int)(implicit F: MonadError[F, E]): F[A] =
F.tailRecM(count) {
case cnt if cnt <= 1 => fa.map(_.asRight)
case cnt => fa.attempt.map(_.leftMap(_ => cnt - 1))
}
}
implicit class MonadErrorEitherTOps[F[_], E, A](val fea: EitherT[F, E, A]) extends AnyVal {
/** sums logic error with underlying error */
def attemptXor[U](implicit F: ApplicativeError[F, U]): EitherT[F, Either[U, E], A] =
EitherT(fea.value.attempt.map(_.assocR))
}
}