规范化验证错误类型

时间:2012-05-05 16:23:25

标签: scala scalaz

我正在尝试找到一种最方便的方法来规范化scalaz.Validations中的for-comprehension中的错误类型。一个“上层”调用方法返回在“较低”层上具有不同错误类型的Validations。当然,需要为每个较低级别的错误类型定义一个映射到一个上层错误类型,但我似乎无法绕过提供明确的类型提示,因为我可以理解我的implicits。我想让for-comprehension的每一行都清除错误类型的显式转换(例如通过.fail.map(...)。validation。我尝试了一种带有IsUpperError类型特征和隐式转换的方法如下:

package errorhandling

import scalaz._
import Scalaz._

class LowerServiceA {
  def doStuff(): Validation[LowerServiceAError, Int] = Success(1)
}
sealed trait LowerServiceAError
// ... more specific error types

class LowerServiceB {
  def doStuff(): Validation[LowerServiceBError, Int] = Success(1)
}
sealed trait LowerServiceBError
// ... more specific error types

class LowerServiceC {
  def doStuff(): Validation[LowerServiceCError, Int] = Success(1)
}
sealed trait LowerServiceCError
// ... more specific error types

sealed trait UpperError {}
// ... more specific error types
trait IsUpperError[E] {
  def apply(e: E): UpperError
}
object IsUpperError {
  implicit val lowerServiceAErrorIsUpperError: IsUpperError[LowerServiceAError] = new IsUpperError[LowerServiceAError] {
    def apply(err: LowerServiceAError) = new UpperError {}
  }

  implicit val lowerServiceBErrorIsUpperError: IsUpperError[LowerServiceBError] = new IsUpperError[LowerServiceBError] {
    def apply(err: LowerServiceBError) = new UpperError {}
  }

  implicit val lowerServiceCErrorIsUpperError: IsUpperError[LowerServiceCError] = new IsUpperError[LowerServiceCError] {
    def apply(err: LowerServiceCError) = new UpperError {}
  }
}

object UpperError {
  implicit def upperError[E: IsUpperError, A](v: Validation[E, A]): Validation[UpperError, A] =
    v.fail.map(e => implicitly[IsUpperError[E]].apply(e)).validation
}

class UpperService(serviceA: LowerServiceA, serviceB: LowerServiceB, serviceC: LowerServiceC) {
  def doStuff(): Validation[UpperError, Int] = {
    for {
      // I'd like to avoid the repeated type-hints or .fail.map(...).validation here
      a <- serviceA.doStuff() // : Validation[UpperError, Int]
      b <- serviceB.doStuff() // : Validation[UpperError, Int]
      c <- serviceC.doStuff()
    } yield a + b + c
  }
}

没有类型提示的编译器错误(2.9.2):

ErrorHandling.scala:56: error: could not find implicit value for evidence parameter of type errorhandling.IsUpperError[java.lang.Object]
  b <- serviceB.doStuff() //: Validation[UpperError, Int]
    ^

找到一个错误

如果做这种事情的愿望暗示我如何处理这种错误处理问题,我也会感激指导。

0 个答案:

没有答案