3

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つのエラーが見つかりました

また、このようなことをしたいという願望が、このようなエラー処理への取り組み方に問題があることを示唆している場合は、ガイダンスをいただければ幸いです。

4

0 に答える 0