Scala 如何与一个未来合作,而这个未来又是一个什么样的未来?

Scala 如何与一个未来合作,而这个未来又是一个什么样的未来?,scala,functional-programming,future,either,Scala,Functional Programming,Future,Either,在我当前的项目中,我使用了或[Result,HandbookModule](Result是一个HTTP状态码)作为返回类型,以便在出现问题时创建正确的状态。我现在已经将我的数据库访问重构为非阻塞的 此更改要求将数据库访问函数的返回类型更改为Future[Result,HandbookModule] 现在我不知道如何将这个函数与另一个返回或[Result,Long]的函数粘合在一起 为了更好地说明我的意思: def moduleDao.getHandbook(偏移量,限制):未来[结果,列表[模块

在我当前的项目中,我使用了
或[Result,HandbookModule]
Result
是一个HTTP状态码)作为返回类型,以便在出现问题时创建正确的状态。我现在已经将我的数据库访问重构为非阻塞的

此更改要求将数据库访问函数的返回类型更改为
Future[Result,HandbookModule]

现在我不知道如何将这个函数与另一个返回
或[Result,Long]
的函数粘合在一起

为了更好地说明我的意思:

def moduleDao.getHandbook(偏移量,限制):未来[结果,列表[模块]]=未来(右(列表(模块(1)))
def NEXTOFSET(偏移量、限制、结果):要么[_,长]=右(1)
def GetHandbook(
抵销:长,
限制:长):未来[任一[结果,(列表[手册模块],长)]={
为了{

结果为了从将来打开方法,您必须阻止它并等待结果。您可以使用
wait.result

但是阻止未来通常不是最好的做法。更多关于这一点

所以你们应该以不同的方式来解决这个问题。你们所面临的实际上是嵌套的monad堆栈的常见问题,它可以用monad转换器来处理

Scala的函数编程库提供了monad transformer的实现

在您的情况下,您可以使用
EitherT.apply
Future[orth[Result,List[Module]]
转换为
EitherT[Future,Result,List[Module]]
EitherT.fromOrth
来提升
orth[\uu,Long]

它可能是这样的:

import cats.data.EitherT
import cats.implicits._
  
def getHandbooks(
   offset: Long,
   limit: Long
): Future[Either[String, (List[String], Long)]] = {
  val result: EitherT[Future, String, (List[String], Long)] = for {
    results <- EitherT(moduleDao.getHandbooks(offset, limit))
    offset  <- EitherT.fromEither[Future](nextOffset(offset, limit, results))
  } yield (results, offset)

  result.value //unwrap result from EitherT
}
导入cats.data.EitherT
进口猫_
def GetHandbook(
抵销:长,
限制:长
):Future[任一[String,(列表[String],Long)]={
val结果:EitherT[Future,String,(List[String],Long)]=for{

结果我不得不对发布的代码进行一些假设和调整/更正,以使其可用。(对于那些想帮助你的人来说,你不会让它变得容易。)

如果可以容忍默认的
Long
值,则当
nextofset()
返回
Left
而不是
Right[Long]
时,将显示为键入check和compile

def getHandbooks(offset: Long
                ,limit : Long
                ): Future[Either[Result, (List[Module], Long)]] =
  moduleDao.getHandbooks(offset,limit).map(_.map(ms => 
    (ms, nextOffset(offset,limit,ms).getOrElse(0L))))

如果我理解正确,您的
左侧
表示错误状态,对吗

如果是这样,我认为您应该重构API,使其既不使用
也不使用
,只需使用失败的
Future
来表示错误状态

// Custom exception that wraps existing Result
case class MyCustomException(result: Result) extends Exception

class ModuleDao {
  ...
  def getHandbooks(offset, limit): Future[List[Module] = {
    // You'd probably want to do this asynchronously
    // But for demonstration purposes
    val origRetVal: Either[Result, List[Module] = ??? // current code returning your Either
    origRetVal match {
      case Right(modules: List[Module]) =>
        Future.successful(modules)
      case Left(result: Result) =>
        // Failed future wrapping custom exception
        Future.failed(MyCustomException(result))
    }
  }
  ...
}

为什么您需要更改它?为什么不只是在案例上,它对未来的计算是有效的?在我提供的示例中,这将起作用,但我也有一些更复杂的案例。尝试创建一个复杂的案例,这样会更容易帮助您。好的,我添加了一个更复杂的示例。希望它有用您的示例不会编译。