使用Shapeless LiftAll收集实例时遇ToTraversable隐式缺失错误
解决Shapeless LiftAll转换为List的编译错误
我来帮你搞定这个编译报错的问题!首先咱们得弄明白为什么会出错:
你代码里的implicitly[LiftAll[Desc, gen.Repr]].instances返回的是一个HList,每个元素都是对应字段类型的Desc实例(这里就是Desc[Foo] :: HNil)。但Scala编译器没法自动推断出这个HList转换为List时的元素最小上界(Lub)——它不知道所有元素都属于Desc[_]这个共同父类型,所以找不到ToTraversable的隐式实例。另外,gen.Repr是路径依赖类型(因为gen是一个值实例),这也会让编译器的类型推断变得更困难。
修正方案1:显式指定List的元素类型
最简单的办法就是给lifted变量显式标注类型,告诉编译器我们要的是List[Desc[_]],这样它就能找到对应的隐式转换了:
import shapeless._ import shapeless.ops.hlist.LiftAll trait Desc[T] { def description: String } case class Foo(f: Int) object Foo { implicit val description: Desc[Foo] = new Desc[Foo] { val description = "foo" } } case class SomeCaseClass(f: Foo) val gen = Generic[SomeCaseClass] // 显式指定类型,帮助编译器推断 val lifted: List[Desc[_]] = implicitly[LiftAll[Desc, gen.Repr]].instances.toList
修正方案2:使用类型成员替代路径依赖类型
把gen.Repr换成Generic[SomeCaseClass]#Repr,让类型更清晰,编译器更容易处理:
import shapeless._ import shapeless.ops.hlist.LiftAll import shapeless.ops.hlist.ToList trait Desc[T] { def description: String } case class Foo(f: Int) object Foo { implicit val description: Desc[Foo] = new Desc[Foo] { val description = "foo" } } case class SomeCaseClass(f: Foo) // 直接使用Generic的类型成员 type CaseClassRepr = Generic[SomeCaseClass]#Repr val instances = implicitly[LiftAll[Desc, CaseClassRepr]].instances // 显式获取ToList隐式实例,避免类型推断问题 val lifted = implicitly[ToList[instances.type, Desc[_]]].apply(instances)
方案3:更简洁的写法
你还可以把Generic和LiftAll的类型直接组合起来,省去中间变量:
val lifted = implicitly[LiftAll[Desc, Generic[SomeCaseClass]#Repr]].instances.toList: List[Desc[_]]
这样写既简洁又能让编译器准确推断出类型转换的隐式实例。
内容的提问来源于stack exchange,提问作者Reactormonk
相关产品推荐
相关产品推荐

