5

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.

Mario Galic
  • 47,285
  • 6
  • 56
  • 98
Anastasia
  • 53
  • 5

2 Answers2

5

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))
Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
3

How about using rightT from EitherT?

for {
  _ <- if (condition) {
    EitherT(callEitherFunction)
  } else {
    EitherT.rightT[Future, ErrorType](())
  }
} yield {
  //Some actions
}
Krzysztof Atłasik
  • 21,985
  • 6
  • 54
  • 76