Consider the signature of retrieveUser
where retrieving a non-existent user is not modelled as an error, that is, it is modelled as Future[Right[None]]
:
def retrieveUser(email: String): Future[Either[Error, Option[User]]]
Does there exist a monad transformer MT
such that we can write
(for {
user <- MT(retrieveUser(oldEmail))
_ <- MT(updateUser(user.setEmail(newEmail)))
} {}).run
Using EitherT
the best I can do is the following:
EitherT(retrieveUser(oldEmail)).flatMap {
case Some(user) =>
EitherT(updateUser(user.setEmail(newEmail)))
case None =>
EitherT.right(Future.successful({}))
}.run
The problem is that mapping over EitherT(retrieveUser(email))
results in Option[User]
, instead of unboxed User
, which breaks the for-comprehension.
OptionT(EitherT(retrieveUser(oldEmail))
with-Ypartial-unification
worked fine in Scalaz. – Mario Galic