Search code examples
scalaconditional-statementsmonad-transformersscala-catseither

EitherT: Call function returning Either only if a certain condition is true (otherwise return right)


So I have a certain function which I need to call only if a certain condition is true. If it's false, I consider it as Right.

I would use EitherT.cond, but the thing is my function's return type is Future[Either[ErrorType, Unit]], so it's not suitable for me. Here's my code which does what I want:

def callEitherFunction: Future[Either[ErrorType, Unit]]

for {
_ <- if (condition) {
     EitherT(callEitherFunction)
   } else {
     Either.right[ErrorType, Unit](()).toEitherT[Future]
   }
} yield {
  //Some actions
}

I wonder if there is a more elegant way to do it. Would appreciate any help.


Solution

  • You can use EitherT.cond as follows:

    cond[Future](!condition, (), ()).leftFlatMap(_ => EitherT(callEitherFunction))
    

    Also, [Future] can be omitted in some contexts, making it even shorter.

    I'm not sure whether it's all that much clearer than the if-else, though: the slightly longer version with if-else might be easier to understand and to maintain in the long run.


    Complete example with all imports:

    import cats.data.EitherT
    import scala.concurrent.Future
    import scala.util.Either
    import cats.syntax.either._
    import cats.instances.future._
    import scala.concurrent.ExecutionContext.Implicits.global
    
    type ErrorType = String
    def callEitherFunction: Future[Either[ErrorType, Unit]] = ???
    def condition: Boolean = true
    
    EitherT.cond(!condition, (), ()).leftFlatMap(_ => EitherT(callEitherFunction))