结合期货、两者和期权进行理解 [英] Combining Futures, Eithers and Options in for comprehensions

查看:33
本文介绍了结合期货、两者和期权进行理解的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一组返回不同类型的方法:

I have a collection of methods that return different types:

Either[ErrorResponse, X]
Future[Either[ErrorResponse, X]]
Option[ErrorResponse]

这些方法需要先前方法的结果来执行计算.方法:

These methods need the result from a previous method to perform their computation. The methods:

type Parameters = Map[String, String]

// allows me to flatmap on an either
implicit def toRightProjection[Failure, Success](e: Either[Failure, Success]) =
  e.right

// converts anything to a future
implicit def toFuture[T](t: T) =
  Future.successful(t)

// retrieves the request paramters from the given request
def requestParameters(request: RequestHeader): Either[ErrorResponse, Parameters] = ???

// retrieves the response type from the given parameters
def responseType(p: Parameters): Either[ErrorResponse, String] = ???

// retrieves the client id from the given parameters
def clientId(p: Parameters): Either[ErrorResponse, String] = ???

// retrieves the client using the given client id
def client(clientId: String): Future[Either[ErrorResponse, Client]] = ???

// validates the response type of the client
def validateResponseType(client: Client, responseType: String): Option[ErrorResponse] = ???

我可以将它们与以下内容连接在一起以进行理解(请注意,我写下了一些类型以阐明计算的特定部分的内容).

I can the wire them together with the following for comprehension (note that I wrote down some types to clarify the contents of specific parts of the computation).

val result: Either[ErrorResponse, Future[Either[ErrorResponse, Client]]] =
  for {
    parameters <- requestParameters(request)
    clientId <- clientId(parameters)
    responseType <- responseType(parameters)
  } yield {
    val result: Future[Either[ErrorResponse, Either[ErrorResponse, Client]]] =
      for {
        errorOrClient <- client(clientId)
        client <- errorOrClient
      } yield validateResponseType(client, responseType).toLeft(client)

    result.map(_.joinRight)
  }

val wantedResult: Future[Either[ErrorResponse, Client]] =
  result.left.map(Future successful Left(_)).merge

上面的代码很乱,我觉得这可以用不同的方式来完成.我读过关于 monad 和 monad 转换器的文章.这些概念对我来说很新,我无法理解.

The above code is quite messy and I feel this can be done differently. I read about monads and monad transformers. The concept of those is very new to me and I can not get my head around it.

大多数示例只处理两种类型的结果:Either[X, Y]Future[Either[X, Y]].我仍然觉得很难改变主意.

Most of the examples only deal with two types of results: Either[X, Y] and Future[Either[X, Y]]. I still find it very hard to bend my mind around it.

我怎样才能写出一个漂亮而干净的理解来代替上述的?

这样的事情会很棒(我不确定这是否可能):

Something like this would be awesome (I am not sure if that is even possible):

val result: Future[Either[ErrorResponse, Client]] =
  for {
    parameters <- requestParameters(request)
    clientId <- clientId(parameters)
    responseType <- responseType(parameters)
    client <- client(clientId)
    _ <- validateResponseType(client, responseType)
  }

推荐答案

好的,这是我的尝试:

import scalaz._, Scalaz._

implicit val futureMonad = new Monad[Future] {
  override def point[A](a: ⇒ A): Future[A] = future(a)

  override def bind[A, B](fa: Future[A])(f: A ⇒ Future[B]): Future[B] =
    fa.flatMap(f)
}

import EitherT._
val result: EitherT[Future, ErrorResponse, Client] =
  for {
    parameters <- fromEither(Future(requestParameters(request)))
    clientId <- fromEither(Future(clientId(parameters)))
    responseType <- fromEither(Future(responseType(parameters)))
    client <- fromEither(client(clientId))
    response <- fromEither[Future, ErrorResponse, Client](Future(validateResponseType(client, responseType).toLeft(client)))
  } yield response

val x: Future[\/[ErrorResponse, Client]] = result.run

这篇关于结合期货、两者和期权进行理解的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆