加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala – 结合EitherT和未来

发布时间:2020-12-16 09:16:46 所属栏目:安全 来源:网络整理
导读:我有一个应用程序对不同的后端系统进行大量调用,并希望使用理解来简化后端系统的流程. 我正在寻求将EitherT(scalaz)和Future(scala 2.10)组合起来,以便我可以捕获第一个潜在错误(其未来或后端系统问题),并向最终用户返回适当的消息.我已经快速查看了一个scal
我有一个应用程序对不同的后端系统进行大量调用,并希望使用理解来简化后端系统的流程.

我正在寻求将EitherT(scalaz)和Future(scala 2.10)组合起来,以便我可以捕获第一个潜在错误(其未来或后端系统问题),并向最终用户返回适当的消息.我已经快速查看了一个scalaz验证,但建议捕获第一个错误,而不是所有的错误是使用EitherT.

我在REPL中尝试一个简单的例子,但是我收到以下错误

错误:找不到参数F的隐含值:scalaz.Functor [scala.concurrent.Future]

import scala.concurrent._
import scalaz._
import Scalaz._
import ExecutionContext.Implicits.global

type EitherFuture[+A] = EitherT[Future,String,A]

def method1Success : EitherFuture[Int] = {
  println("method 1 success")
  EitherT {
    Future {
      1.right
    }
  }
}

def method2Failure : EitherFuture[Int] = {
  println("method 2 failure")
  EitherT {
    Future {
      "fail".left
    }
  }
}

val m1 = method1Success

// problem
m1.isRight

// problem
def methodChain1 = {
  for {
    a <- method1Success
    b <- method2Failure
  } yield b
}

我还是新来的Scala和scalaz,所以任何指针都会很棒.

**更新**

通过包括基于@stew建议的scalaz-contrib,我现在有一个更新的版本,显示了与EitherT和Future组合的综合表现,显示了不同的简单用例后端成功,后端故障和未来的故障

import scala.concurrent._
import scalaz._
import Scalaz._
import ExecutionContext.Implicits.global
import scalaz.contrib._
import scalaz.contrib.std._
import scala.concurrent.duration._

type EitherFuture[+A] = EitherT[Future,A]

// various methods that mimic success or different failures
def methodBackendSuccess : EitherFuture[Int] = {
  println("method backend success")
  EitherT {
    Future {1.right}
  }
}

def methodBackendFailure : EitherFuture[Int] = {
  println("method backend failure")
  EitherT {
    Future { "fail".left}
  }
}

def methodFutureFailure : EitherFuture[Int]  = {
  println("method future failure")
  EitherT {
    Future.failed(new Exception("future failed"))
  }
}

// different combinations for for-comprehensions
def methodChainBackendSuccess = {
  for {
    a <- methodBackendSuccess
    b <- methodBackendSuccess
    c <- methodBackendSuccess
  } yield c
}

def methodChainBackendFailure = {
  for {
    a <- methodBackendSuccess
    b <- methodBackendFailure
    c <- methodBackendSuccess
  } yield c
}

def methodChainFutureFailure = {
  for {
    a <- methodBackendSuccess
    b <- methodFutureFailure
    c <- methodBackendSuccess
  } yield c
}

// process results for different chain methods
def processOutcome(chainMethod: => EitherFuture[Int]):Int = try {
    val x = Await.result(chainMethod.run,30 seconds) 
    x.toEither match {                             
      case Left(l) => {
        println("Backend failure <" + l + ">")
        -1 
      }
      case Right(r) => {
        println("Backend success <" + r + ">") 
        r
      }
    }
  } catch {
    case e: Exception => {
      println("Future error <" + e.getMessage + ">" )
      -99
  }
}

// run tests
val backendSuccess = processOutcome(methodChainBackendSuccess)
val backendFailure = processOutcome(methodChainBackendFailure)
val futureFailure = processOutcome(methodChainFutureFailure)

解决方法

您需要为Future导入或提供一个Functor实例.我建议使用 scalaz-contrib项目中的一个. -contrib是由在scalaz上工作的同一个人工作的一个单独的项目.未来的实例是在这个包中而不是scalaz-core,因为现在,scalaz-core保持了scala 2.9和2.10之间的兼容性.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读