scalaz:如何处理验证中的不同错误类型?

标签 scala validation scalaz

如果我有多个返回具有固定错误类型的东西的 Validation[E, _] 的操作,我可以在 for-comprehension 中使用它们。例如:

val things: Validation[E, (Int, Double)] = for {
  i <- getValidationOfInt
  d <- getValidationOfDouble
} yield (i, d)

如果错误类型不同怎么办?假设我从 HTTP 读取并希望将字符串响应转换为 Int

import scalaz._; import Scalaz._

object ValidationMixing {
  class HttpError

  def getFromHttp: Validation[HttpError, String] = ???
  def parseInt(json: String): Validation[Throwable, Int] =
    Validation.fromTryCatchNonFatal(Integer.parseInt(json))

  val intParsedFromHttp: Validation[Any, Int] = for {
    s <- getFromHttp
    i <- parseInt(s)
  } yield i
}

这会编译,但只是因为 Validation 的错误类型是 Any,是 ThrowableHttpError 的父类(super class)型。这不是很有帮助。

我可以想到各种表示这种组合错误类型的方法,它们比 Any 更有用(例如 Validation[Error1\/Error2, Result] 来存储, Validation[String, Result] 转换为错误消息等),但它们都有缺点。

有没有一种惯用的方法来做到这一点?

最佳答案

由于没有人有更好的主意,我将留下我的答案以供将来引用。

正如评论中所说,最好的方法是创建错误层次结构:

trait GenericError {  /* some commond fields */}
case class MyNumericError(/* fields */)

然后在验证中使用 leftMap 来生成适当的错误:

Validation.fromTryCatchNonFatal(...).leftMap(t => MyNumericError(...))

这种方法有两个优点

  • 首先,您将始终有一个Validation[GenericError, T],因此该验证的左侧部分不会有不同的类型
  • 其次,这有助于为开发人员和服务用户生成有意义的错误,同时请注意,在您拥有许多上下文信息的情况下生成错误有助于此过程。

关于scalaz:如何处理验证中的不同错误类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34612430/

相关文章:

scala - 扩展 Scala 集合

jquery 验证仅在正则表达式中不起作用

java - SpringMVC验证: Set specific error message for each validation check

scala - 是否有可以与组合器组合的最大数量的验证?

scala - akka Camel vs scalaz Camel

Scala akka http 服务器 - 打印 POST 消息

python - 为什么这个简单的 Spark 程序没有使用多核?

scala - 如何检查列表是否包含所有相同的值?

ruby-on-rails - Rails 4 - 提交后重定向到正确的网址

scala - 可以使用 scalaz Arrow 组合吗?