依赖类型的隐式扩展

时间:2015-02-22 17:01:21

标签: scala types implicit-conversion

我想知道为什么以下情况不起作用。假设我有两种类型:

trait Def[T]
trait Ref[T]
case class Module()

我想将Def转换为Ref,因此我宣布以下方法:

object Ref {
  implicit def fromDef[A](defin: Def[A])(implicit rc: RefConverter[A]): Ref[rc.ResType] = new Ref[rc.ResType] {}
}

但是以防万一:

val moduleDef: Def[Module] = ???
val moduleRef: Ref[Module] = moduleDef

Scala编译器无法找到正确的转换方式(即fromDef函数),但如果我们明确告诉它使用此转换,即Ref.fromDef(moduleDef),scalac会找到正确的{{ 1}}实例。另一个需要考虑的重要事项是,如果我将结果类型更改为RefConverter,它也会解析转换链。那么编译器无法解析具有依赖结果类型的链?

3 个答案:

答案 0 :(得分:2)

您必须将类型参数和类型成员绑定在一起。

您可以在其他答案中提供别名;请注意,它不适用于特征中绑定的类型,请参阅代码注释。

但是你可以提供另一种有界的类型参数:

trait Ref[T]
trait Def[T]
case class Module()

object Ref {
  //implicit def fromDef[A](defin: Def[A])(implicit rr: RefResolver[A]): Ref[rr.RefType] = new Ref[rr.RefType] {}
  //implicit def fromDef[A](defin: Def[A])(implicit rr: RefResolver[A]): Ref[A] = new Ref[A] {}  // OP notes that this works
  implicit def fromDef[A, B <: A](defin: Def[A])(implicit rr: RefResolver[B]): Ref[B] = new Ref[B] {}
  // or
  implicit def fromDef[A](defin: Def[A])(implicit rr: RefResolver[A]): Ref[A] { type RefType <: A } = new Ref[A] { type RefType = A }
}

trait RefResolver[A] {
  type RefType
  //type RefType <: A    // not good enough
}

object RefResolver {
  implicit val moduleRes: RefResolver[Module] { type RefType = Module } =
    new RefResolver[Module] {
      type RefType = Module
    }
}

object Test extends App {
  val moduleDef: Def[Module] = new Def[Module] {}
  val moduleRef: Ref[Module] = moduleDef
}

答案 1 :(得分:0)

以下编译:

trait Def[T]
trait Ref[T]
case class Module()

trait RefConverter[T]{
  type ResType = T
  type RefType = T
}
object Ref {
  implicit def fromDef[A](defin: Def[A])(implicit rc: RefConverter[A]): Ref[rc.ResType] = new Ref[rc.RefType] {}
}
implicit val rc = new RefConverter[Module]{}
val d = new Def[Module]{}
val r = d:Ref[Module]

答案 2 :(得分:0)

这会编译并打印类型:

object Test extends App {

  implicit val rc = new RefConverter[Module] {}

  object Ref {
    implicit def fromDef[A](defin: Def[A])(implicit rc: RefConverter[A]): Ref[rc.ResType] = new Ref[rc.ResType] {}
  }

  val moduleDef: Def[Module] = new Def[Module]() {}
  val moduleRef: Ref[Module] = moduleDef

  println(moduleDef.getClass.getName)
  println(moduleRef.getClass.getName)

  trait RefConverter[T] {
    type ResType = T
  }

  trait Def[T]

  trait Ref[T]

  case class Module()
}

我认为你的Refconverter要么不在范围内,要么你的IDE误导了你的错误。