scala - 为什么这个隐含的决议失败了?
问题描述
我有一个隐式转换 - 下面 - 感觉它肯定应该工作,但绝对不是。任何人都可以解释一下吗?我知道implicitly
在使用类型改进时有时会失败 - 这是这里的问题吗?
trait GetItem[A[_], T, R] {
type Out
def ret(a: A[T], ref: R): Out
}
object GetItem {
implicit def ifRefIsInt[A[_], T]: GetItem[A, T, Int] { type Out = A[T] } = new GetItem[A, T, Int] {
type Out = A[T]
def ret(a: A[T], ref: Int): Out = a
}
}
import GetItem._
//this works fine:
val t: GetItem[List, Double, Int] { type Out = List[Double] } = ifRefIsInt[List, Double]
// so does this:
implicitly[GetItem[List, Double, Int] { type Out = List[Double] }](t)
// this does not:
implicitly[GetItem[List, Double, Int] { type Out = List[Double] }]
// Could not find implicit parameter for value e: Example.Main.GetItem[List, Double, Int]{type Out = List[Double]}
非常感谢任何帮助,我已经盯着这个看了一段时间,但收效甚微。
解决方案
不知道为什么它不能那样工作,但是解决这类问题的一个好技术是使用Aux模式将类型成员提升为类型参数,这可以提高分辨率。
trait GetItem[A[_], T, R] {
type Out
def ret(a: A[T], ref: R): Out
}
object GetItem {
type Aux[A[_], T, R, O] = GetItem[A, T, R] { type Out = O }
implicit def ifRefIsInt[A[_], T]: Aux[A, T, Int, A[T]] = new GetItem[A, T, Int] {
type Out = A[T]
def ret(a: A[T], ref: Int): Out = a
}
}
您可以像这样测试:
implicitly[GetItem.Aux[List, Double, Int, List[Double]]]
// res: GetItem.Aux[List, Double, Int, List[Double]] = ...
implicitly[GetItem[List, Double, Int]]
// res: GetItem[List, Double, Int] = ...
推荐阅读
- javascript - 为工作区建立一个可移动的视口
- python - 使用 SELECT 检索数据并单独处理
- ruby-on-rails - 在 Rails 和 Postgresql 中使用 JSONB
- mysql - 使用 JOIN 时的 SQL CASE
- asp.net-core - 我有一个 angular 8 的 netcore 3.1 Web 应用程序,在我的本地运行良好。但是当部署到服务器上的 IIS 时,api 似乎不起作用
- c# - 如何使图像(或矩形)遵循样条线
- asp.net - 显示项目的详细信息 Asp.net MVC
- apache-kafka - Kafka如何向具体用户发送消息?
- vue.js - Nuxt js 上的 vue-awesome-swiper(swiperjs) 不能在生产环境中工作,但可以在开发环境中工作
- c++ - 表达式必须有一个常量值