scalazの理解のためにエラータイプを正規化する最も便利な方法を見つけようとしています。「下位」レイヤーで異なるエラータイプの検証を返すメソッドを呼び出す1つの「上位」レイヤーでの検証。当然、各下位レベルのエラータイプから上位層のエラータイプへのマッピングを定義する必要がありますが、暗黙的に取得するための理解のために、明示的なタイプヒントを提供することを回避できないようです。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]
^
1つのエラーが見つかりました
また、このようなことをしたいという願望が、このようなエラー処理への取り組み方に問題があることを示唆している場合は、ガイダンスをいただければ幸いです。