隐含的更具体的类型没有被提起

时间:2014-06-11 04:53:39

标签: scala

我正在构建一个小型库,为Serialize和Deserialize添加一个类型类。我创建了一个隐式,它围绕一个scalaz Validation包装结果,但是将其余的委托给另一个隐式的(下面的代码)。我的问题是,在Serialize中,有一个validateSer接受Serialize [A,B]并返回Serialize [A,Validation [Throwable,B]]。这工作正常,但是当我为Deserialize执行相同操作时,编译器无法确定要使用哪个隐式。如何才能使用序列化和反序列化?

序列化

trait Serialize[A, B] {
  def serialize(a: A): B
}

object Serialize {

  import scalaz.@@
  import Format._

  implicit def validateSer[A, B](implicit ser: Serialize[A, B]): Serialize[A, Validation[Throwable, B]] =
    new Serialize[A, Validation[Throwable, B]] {
      override def serialize(t: A): Validation[Throwable, B] =
        Validation.fromTryCatch(ser.serialize(t))
    }

  implicit def jsonSerString[A]: Serialize[A, String @@ JSON] = new Serialize[A, String @@ JSON] {
    override def serialize(t: A): String @@ JSON =
      JSON(mapper.writeValueAsString(t))
}

object HardTypeForJackson
HardTypeForJackson.serialize[Validation[Throwable, String @@ JSON]] // works

反序列化

trait Deserialize[A, B] {
  def deserialize(a: A): B
}

object Deserialize {
  import scalaz.@@
  import Format._

  implicit def validateDes[A, B](implicit des: Deserialize[A, B]): Deserialize[A, Validation[Throwable, B]] =
    new Deserialize[A, Validation[Throwable, B]] {
      override def deserialize(a: A): Validation[Throwable, B] =
        Validation.fromTryCatch(des.deserialize(a))
    }

  implicit def jsonDesString[B: Manifest]: Deserialize[String @@ JSON, B] = new Deserialize[String @@ JSON, B] {
    override def deserialize(a: String @@ JSON): B =
      mapper.readValue[B](a)
}

JSON("foo").deserialize[Validation[Throwable, PuppetCommand]] // compiler error

    Error:(82, 41) ambiguous implicit values:
 both method validateDes in trait DeserializeInstances of type [A, B](implicit des: com.gopivotal.heimdall.util.Deserialize[A,B])com.gopivotal.heimdall.util.Deserialize[A,scalaz.Validation[Throwable,B]]
 and method jsonDesString in trait DeserializeInstances of type [B](implicit evidence$1: Manifest[B])com.gopivotal.heimdall.util.Deserialize[scalaz.@@[String,com.gopivotal.heimdall.util.Format.JSON],B]
 match expected type com.gopivotal.heimdall.util.Deserialize[scalaz.@@[String,com.gopivotal.heimdall.util.Format.JSON],scalaz.Validation[Throwable,com.gopivotal.heimdall.orchestration.PuppetCommand]]
    val parsed = JSON("foo").deserialize[Validation[Throwable, PuppetCommand]]

1 个答案:

答案 0 :(得分:0)

好的,我上面的代码不是我用的。我有一个名为DeserializeInstances的特征中的所有含义,而Deserialize对象只是扩展了它。当我将验证隐式移动到对象而不是特征中时,它会按预期被拾取。