当前位置: 首页 > 知识库问答 >
问题:

结合EitherT和未来

能翔宇
2023-03-14

我有一个对不同后端系统进行大量调用的应用程序,并希望使用for-comprehensions来简化后端系统的流程。

我希望将AoseT(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建议的scaraz-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, String, 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)

共有2个答案

向修谨
2023-03-14

查看在以下任一项上定义的< code>isRight的签名:

def isRight(implicit F: Functor[F]): F[Boolean]

它需要一个用你的EitherT的类型参数参数化的函子,在你的例子中是Future。Scalaz没有为Future类型提供隐式函子,您需要按照这个模型编写自己的:

http://scalaz.github.io/scalaz/scalaz-2.9.0-1-6.0/doc.sxr/scalaz/Functor.scala.html

请注意每个支持类型的所有隐式def。

缪成天
2023-03-14

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

 类似资料:
  • 问题内容: 我想在CSS(或任何其他伪选择器)中结合使用。我基本上有一个列表,并且该类的项目具有使用施加的箭头形状。我希望对悬停的对象也是如此,但不能完全使其正常工作。继承人代码 问题答案: 只需以与选择器相同的方式将其追加到选择器即可:

  • 问题内容: 我目前的构建数量至少为10,因此我必须使用该库来实现。我已经设置了,但是我现在要添加一个,但是这需要扩展我的类,Java没有多个。我该怎么办? 问题答案: ListActivity尚未移植到AppCompat。可能是因为您应该认为它“已弃用”,而改用ListFragment。 片段将与ActionBarActivity一起使用,只需确保它们是支持库中的片段即可。 要通过读这大约片段的链

  • 问题内容: 我正在使用CodeIgniter编写的现有站点上工作,我们正在考虑将AngularJS用于需要大量前端功能的某些页面,但我们不想替换所有CodeIgniter视图(一次(尚未))。 因此,我单击了由angular的路由器控制的链接,该链接由javascript处理,但下一个链接可能是应由CodeIgniter框架处理的“正常”请求。 有两种结合这两种方法的优雅方法吗?我真的不介意一些额

  • 你知道是否可以用PDFBox填写PDF格式的表格吗?如果是的话,是否有代码示例或教程来实现这一点?若否,有何最佳选择可达致这个目标?

  • 主要内容:示例YAML包括使用缩进范围的块集合。 在这里,每个条目都以一个新行开头。 集合中的块序列表示每个条目带有破折号和空格( )。 在YAML中,块集合样式不由任何特定指示符表示。 YAML中的块集合可以与其他标量数量区分开来,并且包含其中包含的键值对的标识。 映射是JSON结构中包含的键值的表示。 它经常用于多语言支持系统以及在移动应用程序中创建API。 映射使用键值对表示以及冒号和空格()的使用。 示

  • 问题内容: 好的,所以我正在学习I / O,并且在其中一张幻灯片中找到了以下代码。有人可以解释一下为什么需要FileWrite,BufferedWriter和PrintWriter吗?我知道BufferedWriter将缓冲输出并将其全部放入,但是为什么他们要使用FileWriter和PrintWriter?他们在错误处理等方面做得差不多吗? 而且为什么他们传递到? 问题答案: 大概他们之所以使用