Scala中如何让Test类p2方法自动获取IterableFactory上下文给定实例?
让Scala中Test类的p2方法自动推导IterableFactory的解决方案
我定义了如下Test类:
import scala.collection.{IterableFactory, Factory} class Test: def p1[C[_]](xs: Int*)(using f: Factory[Int, C[Int]]): C[Int] = f.fromSpecific(xs) def p2[C[_]](xs: Int*)(using f: IterableFactory[C]): C[Int] = f(xs*)
由于List、Seq等集合类中定义了implicit def iterableFactory[A]: Factory[A, CC[A]] = IterableFactory.toFactory(this)这样的隐式方法,调用p1时可以直接写:
val t = new Test t.p1[List](1, 2, 3)
但调用p2时,无法直接写t.p2[List](1, 2, 3),必须手动定义given IterableFactory[List]或者写成t.p2(1, 2, 3)(using List)。请问有没有办法让t.p2[List](1, 2, 3)自动生效?比如在Test的伴生对象中定义给定实例?
方案1:为常用集合显式提供Given实例
在Test的伴生对象中,为你需要用到的集合类型直接提供IterableFactory的given实例:
object Test: // 为List提供IterableFactory实例 given IterableFactory[List] = List // 为Seq提供IterableFactory实例 given IterableFactory[Seq] = Seq // 其他需要的集合类型同理添加
添加后即可直接调用t.p2[List](1, 2, 3),Scala会自动匹配对应的given实例。
方案2:通用隐式推导(支持所有标准集合)
如果想覆盖所有标准集合(它们的伴生对象均实现了IterableFactory接口),可以在Test的伴生对象中定义通用隐式方法,通过反射自动获取集合的伴生对象作为IterableFactory实例:
object Test: import scala.reflect.ClassTag implicit def getIterableFactory[C[_]](using ct: ClassTag[C[_]]): IterableFactory[C] = val companion = ct.runtimeClass.getDeclaredField("MODULE$").get(null).asInstanceOf[IterableFactory[C]] companion
这个方案无需为每个集合单独配置,只要集合的伴生对象符合IterableFactory类型,就能自动推导。反射带来的性能开销极小,多数场景可忽略。
方案3:调整方法定义(最优雅的推荐方案)
直接修改Test类中p2方法的定义,利用Scala 3的上下文绑定简化隐式参数的处理:
class Test: def p1[C[_]](xs: Int*)(using f: Factory[Int, C[Int]]): C[Int] = f.fromSpecific(xs) // 用上下文绑定替代显式using参数,要求C的伴生对象实现IterableFactory[C] def p2[C[_]: IterableFactory](xs: Int*): C[Int] = summon[IterableFactory[C]](xs*)
修改后,直接调用t.p2[List](1, 2, 3)即可,编译器会自动将List伴生对象作为隐式实例传入,无需额外配置。
内容的提问来源于stack exchange,提问作者esse
相关产品推荐
相关产品推荐

