如何对更高类型参数化的值集合执行映射?存在类型编译错误求助
解决Scala中存在类型在高阶类型映射时的编译错误
我来帮你搞定这个编译报错的问题!你遇到的can't existentially abstract over parameterized type C错误,本质是Scala 2对包含高阶类型的存在类型(forSome定义的那种)有处理限制,尤其是在map这类需要推导返回类型的场景下。
先再明确下你的问题代码,方便大家理解:
type Cons[X] class Higher[C[X] <: Cons[X]] type AnyHigher = Higher[C] forSome { type C[X] <: Cons[X] } // 这行代码触发编译错误 Seq[AnyHigher]().map { h => h }
为啥会报错?
Scala 2的存在类型在处理内部包含参数化高阶类型(比如你这里的C[X])时,没法在map的类型推导过程中正确完成类型抽象。map需要明确知道函数的输入输出类型,但AnyHigher里的C[X]是被隐藏的存在类型,编译器不知道怎么为返回值生成合法的类型抽象,于是就抛出了这个错误。
给你几个可行的解决办法:
办法1:用泛型Trait封装替代存在类型
别直接用forSome定义AnyHigher,改成用一个泛型Trait来包裹Higher实例,把内部的类型信息藏在Trait里:
type Cons[X] class Higher[C[X] <: Cons[X]] // 用Trait封装存在类型的信息 trait AnyHigher { type C[X] <: Cons[X] val value: Higher[C] } // 加个辅助构造方法,方便创建实例 object AnyHigher { def apply[C0[X] <: Cons[X]](h: Higher[C0]): AnyHigher = new AnyHigher { type C[X] = C0[X] val value = h } } // 现在map就能正常跑了 Seq[AnyHigher]().map { ah => ah.value }
这种方式把存在类型的细节封装起来,编译器能正确处理map的类型推导,不会再卡壳。
办法2:升级到Scala 3(如果可行的话)
Scala 3彻底重构了存在类型的处理逻辑,语法更简洁,限制也少了很多。你可以直接用通配符简化AnyHigher的定义,报错问题直接消失:
type Cons[X] class Higher[C[X] <: Cons[X]] type AnyHigher = Higher[_[X] <: Cons[X]] // Scala 3的简化存在类型写法 // 这时候map完全没问题 Seq[AnyHigher]().map { h => h }
办法3:显式指定map的类型参数(临时 workaround)
如果暂时没法改代码结构或者升级Scala版本,你可以强制指定map的输出类型,绕过编译器的自动推导:
type Cons[X] class Higher[C[X] <: Cons[X]] type AnyHigher = Higher[C] forSome { type C[X] <: Cons[X] } // 显式告诉编译器map的输出类型是AnyHigher Seq[AnyHigher]().map[AnyHigher]({ h => h })
这个办法能快速解决报错,但不算特别优雅,适合临时救急。
内容的提问来源于stack exchange,提问作者Turin
相关产品推荐
相关产品推荐

