Scala 2/3中无需匹配类型的高种类参数提取器实现方案
问题背景
在Scala 3中尝试用匹配类型定义高种类参数提取器Ext来提取Seq的元素类型,代码如下:
type Ext[S <: Seq[_]] = S match { case Seq[t] => t } trait XX[A, B <: Seq[A]] trait XX1[B <: Seq[_]] extends XX[Ext[B], B]
该实现在简单场景可用,但结合类型类时出现类型推导失败的问题:
implicitly[Ext[Seq[Int]] =:= Int] // 报错:Cannot prove that e.Ext[Seq[Int]] =:= Int
经排查,带Seq上下界的定义会触发此问题,以下是Scala 2/3中不使用匹配类型的可行实现方案:
方案1:Scala 2/3通用 - 类型类+隐式证据
通过定义类型类关联Seq类型与其元素类型,依靠隐式推导完成类型提取,这种方式兼容性强,在类型类场景下表现稳定:
// 定义类型类,用于提取Seq的元素类型 trait SeqElementExtractor[S <: Seq[_]] { type Element } // 为所有Seq[T]提供隐式实例,绑定Seq[T]和T的关联关系 object SeqElementExtractor { // 辅助类型,简化显式指定类型的写法 type Aux[S <: Seq[_], E] = SeqElementExtractor[S] { type Element = E } implicit def seqElementExtractor[T]: Aux[Seq[T], T] = new SeqElementExtractor[Seq[T]] { type Element = T } } // 定义别名`Ext`,简化类型提取的调用 type Ext[S <: Seq[_]] = SeqElementExtractor[S]#Element // 原有的XX、XX1定义可直接复用,类型推导正常 trait XX[A, B <: Seq[A]] trait XX1[B <: Seq[_]] extends XX[Ext[B], B] // 验证类型推导正确性 implicitly[Ext[Seq[Int]] =:= Int] // 编译通过
方案2:Scala 3专属 - 利用内置类型成员+隐式推导
Scala 3中可以借助Seq的内置类型特性,结合隐式进一步简化实现:
// 定义提取器特质 trait SeqElem[S] { type E } // 为Seq[T]提供隐式实例,绑定元素类型 implicit def seqElem[T]: SeqElem[Seq[T]] { type E = T } = new SeqElem[Seq[T]] { type E = T } // 定义Ext别名 type Ext[S <: Seq[_]] = SeqElem[S]#E // 验证 implicitly[Ext[Seq[Int]] =:= Int] // 编译通过
内容的提问来源于stack exchange,提问作者tribbloid
相关产品推荐
相关产品推荐

