如何按类型参数合并Foo与Bar两个Typeclass的实例集合?
Scala中合并同类型参数的Typeclass实例集合
最优直接方案:提前绑定配对实例
如果能控制实例的收集流程,直接将同类型参数A的Foo[A]和Bar[A]绑定在一起是最简洁的方案,完全避免后续合并的麻烦:
// 定义封装同类型配对实例的类 case class FooBar[A](foo: Foo[A], bar: Bar[A]) // 直接收集该类的实例集合 val fooBarSet: Set[FooBar[_]] = ...
后续需要使用时,可通过模式匹配提取具体类型的配对:
fooBarSet.foreach { case FooBar(foo: Foo[Int], bar: Bar[Int]) => // 处理Int类型的配对实例 case FooBar(foo: Foo[String], bar: Bar[String]) => // 处理String类型的配对实例 }
已有两个独立集合时的方案:基于类型标识映射配对
如果已经存在两个分开的Set[Foo[_]]和Set[Bar[_]],可以给Typeclass添加类型标识,转成Map后按标识配对(比遍历集合做模式匹配更高效):
import scala.reflect.ClassTag // 修改Typeclass,添加类型标识方法 trait Foo[A] { def classTag: ClassTag[A] // 原有方法... } trait Bar[A] { def classTag: ClassTag[A] // 原有方法... } // 将集合转为以类型标识为键的Map val fooMap = seqFoo.map(f => f.classTag -> f).toMap val barMap = seqBar.map(b => b.classTag -> b).toMap // 提取同时存在于两个Map中的类型标识,生成配对实例集合 val fooBarPairs: Set[(Foo[_], Bar[_])] = fooMap.keySet.intersect(barMap.keySet).map(tag => (fooMap(tag), barMap(tag)))
注:如果需要区分泛型类型(如
List[Int]和List[String]),可以将ClassTag替换为TypeTag,逻辑完全一致。
内容的提问来源于stack exchange,提问作者HydraMazay
相关产品推荐
相关产品推荐

