首页 > 解决方案 > 结果类型是泛型类型上的类型投影的隐式转换

问题描述

我有一些基本上归结为这个的 scala 2.13 代码

import scala.language.implicitConversions

trait Base {
  type V
  def v: V
}

case class Derived(v: Int) extends Base {
  type V = Int
}


object TestImplicitConversion {
  implicit def getV[T <: Base](a: T): T#V = a.v

  val a: Int = Derived(5)
}

在这里,我希望编译器使用隐式转换getV来转换DerivedInt,但代码无法编译。手动添加对 , 的调用getV将使代码编译。有人可以帮我理解为什么在标准中解释了转换。

我发现进行这种转换的方法是添加第二个通用参数和约束

implicit def getV2[T <: Base, S](a: T)(implicit constraint: T#V =:= S): S = constraint(a.v)

在这个版本中,编译器使用转换并且代码编译。

编辑:

@user 使用细化类型提供的替代解决方案确实似乎是一种更好的方法。但它并没有真正解释为什么它的原始实现不起作用。所以我仍然有兴趣了解为什么编译器在显式调用将使代码编译时不使用隐式 def。

标签: scalaimplicit-conversionimplicittype-projection

解决方案


正如 gianluca aguzzi 在评论中提到的那样,类型投影是不健全的,应该避免。此外,T它不是一个具体的类型,所以无论如何你都不能在它上面使用投影。您只能接受Base#V作为类型参数,并为 的类型使用细化类型a

implicit def get[T](a: Base { type V = T }): T = a.v

因此,您可以避免投射和类型投影。

斯卡斯蒂


推荐阅读