Scala 3如何正确实现含多类型参数的匹配类型(Match Type)
问题原因
- 你返回值声明用了
C2[x.type, y.type],这里的x.type、y.type是对应值的单例类型,比方法泛型参数N、M的范围更窄,普通模式匹配的类型推导只能确认N、M的实际类型,无法直接关联到单例类型对应的匹配类型归约结果。 - 嵌套匹配类型的归约需要编译器将模式匹配分支的类型约束同步到匹配类型的推导逻辑中,普通
def的模式匹配不会自动完成这个同步:就算你在分支里匹配到y是Int,编译器也没法把这个事实和内层M match { case Int => Int }的归约关联,自然会认为返回的Int和要求的匹配类型不兼容。 - 你之前的元组写法可以运行,本质是加了
@unchecked注解,主动跳过了编译器的分支类型检查,嵌套写法没有做类似的跳过处理,所以会抛出类型错误。
解决方案
有两种可选方案,优先推荐第一种编译时安全的写法:
方案1:使用inline模式匹配(类型安全)
给方法和每一层模式匹配都加上inline关键字,编译器会在编译时展开分支,自动完成匹配类型的归约,不需要手动跳过类型检查:
// 扩展嵌套匹配类型覆盖你原有的全部3种case type C2[N, M] = N match { case String => M match { case Int => Int case String => Int } case Int => M match { case String => Int } } // 用inline def + inline模式匹配 inline def fn[M, N](x: N, y: M): C2[N, M] = inline x match { case xx: String => inline y match { case yy: Int => xx.size + yy case yy: String => xx.size + yy.size } case xx: Int => inline y match { case yy: String => xx + yy.size } }
测试可以正常运行:
println(fn("abc", 123)) // 输出126 println(fn("abc", "def")) // 输出6 println(fn(123, "def")) // 输出126
方案2:手动跳过类型检查(和原有元组写法逻辑一致)
如果不想改inline写法,可以和你之前的实现一样,手动给返回值加强转,告诉编译器你自己对类型正确性负责:
type C2[N, M] = N match { case String => M match { case Int => Int case String => Int } case Int => M match { case String => Int } } def fn[M,N](x:N,y:M):C2[N,M] = x match { case xx: String => y match { case yy: Int => (xx.size + yy).asInstanceOf[C2[N,M]] case yy: String => (xx.size + yy.size).asInstanceOf[C2[N,M]] } case xx: Int => y match { case yy: String => (xx + yy.size).asInstanceOf[C2[N,M]] } }
内容的提问来源于stack exchange,提问作者ndas
相关产品推荐
相关产品推荐

