Scala优先取隐式实例降级走派生的Provider类型类问题排查
问题根因
- 隐式优先级继承链缺失:你定义的
LowPriorityProvider未被Provider伴生对象继承,低优先级的派生隐式方法完全不在Provider的隐式搜索范围内,编译器根本无法感知到provideDerivation的存在。 - 派生方法类型参数无法推导:原
provideDerivation的两个泛型参数From和To无关联约束,当你需要获取Provider[NamesFor[Test]]时,编译器只能确定To=NamesFor[Test],完全无法推导From应该为Test,自然找不到对应的Deriver[Test, NamesFor[Test]]实例。
修复方案
步骤1:补全隐式优先级继承关系
让Provider伴生对象继承LowPriorityProvider,让低优先级的派生方法进入隐式搜索范围:
object Provider extends LowPriorityProvider { // 新增继承 implicit def provideInstance[ T ]( implicit inst : T, ) : Provider[ T ] = new Provider[T] { override def provide : T = inst } }
步骤2:修正派生方法的类型参数关联
调整provideDerivation的签名,让编译器可以从目标类型推导出源类型,两种改法可选:
方案A:适配当前NamesFor场景(最简)
直接关联源类型和目标类型的关系:
trait LowPriorityProvider { implicit def provideDerivation[ T ]( implicit deriver : Deriver[ T, NamesFor[T] ], ) : Provider[ NamesFor[T] ] = new Provider[ NamesFor[T] ] { override def provide : NamesFor[T] = deriver.derive } }
方案B:通用支持任意类型类派生
如果你后续要扩展支持Circe、Tapir等其他第三方库的类型类派生,可以用高阶类型做通用适配:
trait LowPriorityProvider { // TC为类型类的类型构造器,比如NamesFor、Encoder、Schema等 implicit def provideDerivationForTC[TC[_], T]( implicit deriver : Deriver[ T, TC[T] ], ) : Provider[ TC[T] ] = new Provider[ TC[T] ] { override def provide : TC[T] = deriver.derive } }
验证效果
修改后你之前报错的场景即可正常运行:
case class Test( int : Int ) val provider = implicitly[ Provider[ NamesFor[ Test ] ] ] println( provider.provide.names ) // 正常输出:int :: HNil
同时原有两个正常场景的逻辑不受影响,显式声明的NamesFor[T]实例优先级依然高于派生结果。
内容的提问来源于stack exchange,提问作者John Hungerford
相关产品推荐
相关产品推荐

