未来的Monad变压器[[错误,选项[用户]]]

时间:2018-05-05 13:16:36

标签: scala monads scalaz monad-transformers

考虑retrieveUser的签名,其中检索不存在的用户不会被建模为错误,也就是说,它被建模为Future[Right[None]]

def retrieveUser(email: String): Future[Either[Error, Option[User]]]

是否存在monad变换器MT,以便我们可以写

(for {
  user <- MT(retrieveUser(oldEmail))
  _    <- MT(updateUser(user.setEmail(newEmail)))
} {}).run

使用EitherT我能做的最好的事情如下:

EitherT(retrieveUser(oldEmail)).flatMap {
  case Some(user) =>
    EitherT(updateUser(user.setEmail(newEmail)))

  case None => 
    EitherT.right(Future.successful({}))
}.run

问题在于,EitherT(retrieveUser(email))上的映射会产生Option[User],而不是取消装箱User,从而打破了理解。

1 个答案:

答案 0 :(得分:3)

我假设参数的顺序与EitherT form Scala Cats中的相同:EitherT[F[_], A, B]基本上只是F[Either[A, B]]的包装。

同样,OptionT[F, A]F[Option[A]]的包装。

因此,

OptionT[EitherT[Future, Error, ?], A]

的包装
EitherT[Future, Error, Option[A]]

又是

的包装
Future[Either[Error, Option[A]]]

因此,

OptionT[EitherT[Future, Error, ?], User](
  EitherT[Future, Error, Option[User]](retrieveUser(oldEmail))
)

应该使用the non/kind-projector)进行类型检查,并且使用-Ypartial-unification类型也应该自动推断,因此您可以尝试使用

OptionT(EitherT(retrieveUser(oldEmail))
在for-comprehensions里面。