我正在尝试找到一种最方便的方法来规范化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]
^
找到一个错误
如果做这种事情的愿望暗示我如何处理这种错误处理问题,我也会感激指导。