scala - 结果类型是泛型类型上的类型投影的隐式转换
问题描述
我有一些基本上归结为这个的 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
来转换Derived
为Int
,但代码无法编译。手动添加对 , 的调用getV
将使代码编译。有人可以帮我理解为什么在标准中解释了转换。
我发现进行这种转换的方法是添加第二个通用参数和约束
implicit def getV2[T <: Base, S](a: T)(implicit constraint: T#V =:= S): S = constraint(a.v)
在这个版本中,编译器使用转换并且代码编译。
编辑:
@user 使用细化类型提供的替代解决方案确实似乎是一种更好的方法。但它并没有真正解释为什么它的原始实现不起作用。所以我仍然有兴趣了解为什么编译器在显式调用将使代码编译时不使用隐式 def。
解决方案
正如 gianluca aguzzi 在评论中提到的那样,类型投影是不健全的,应该避免。此外,T
它不是一个具体的类型,所以无论如何你都不能在它上面使用投影。您只能接受Base#V
作为类型参数,并为 的类型使用细化类型a
:
implicit def get[T](a: Base { type V = T }): T = a.v
因此,您可以避免投射和类型投影。
推荐阅读
- pytorch - 相同重构输入的骰子分数变化
- c# - 将 wpf 应用程序输出重定向到文件
- php - 读取存储在数据库中的 CSV 文件并在 Laravel 的 html 表中查看
- maven - Surefire 无法在 Surefire 报告中生成失败测试的完整堆栈跟踪
- .net-core - dotnet-gcdump 意外转储大小和影响
- amazon-web-services - ALB 侦听器 443 使用 8443 端口问题进行规则
- reactjs - React Native 循环动画动画
- logstash - logstash 将 ruby 代码转换为 logstash 过滤器
- python - Plotly-Dash:如何仅更新图形数据而不更改图形布局?
- pandas - 如何将表格数据(Pandas Dataframe)重塑为 RNN 的 3D 数据?