【问题标题】:Implicit expansion with dependant types依赖类型的隐式扩展
【发布时间】:2015-02-22 17:01:21
【问题描述】:

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

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 会找到正确的RefConverter 实例。要考虑的另一件重要事情是,如果我将结果类型更改为Ref[A],它也会解析转换链。那么编译器无法解析依赖结果类型的链?

【问题讨论】:

  • #ResType 和#RefType 有什么区别?

标签: scala types implicit-conversion


【解决方案1】:

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

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

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

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
}

【讨论】:

  • 这是一个很好的解决方案并回答了问题,但实际上不是很实用,因为它将依赖类型限制为A,所以如果我有一个独立类型ModuleId 并想写@987654324 @这行不通
【解决方案2】:

以下编译:

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]

【讨论】:

  • Arseniy,我很抱歉,但这只是一个错字,只有一个 ResType
【解决方案3】:

这会编译并打印类型:

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 误导,强调这是一个错误。

【讨论】:

    猜你喜欢
    • 2014-11-17
    • 2012-12-29
    • 2016-06-22
    • 2014-06-05
    • 2010-11-20
    • 2016-06-18
    • 1970-01-01
    • 2019-11-12
    • 2017-07-01
    相关资源
    最近更新 更多