Scala 3如何实现返回递归匹配类型的递归函数?
实现返回递归匹配类型的函数编译失败
复现代码
参考标准库元组Append匹配类型实现同名函数时触发类型不匹配错误,代码如下:
// 提取自标准库的Tuple Append匹配类型定义 type Append[X <: Tuple, Y] <: Tuple = X match { case EmptyTuple => Y *: EmptyTuple case x *: xs => x *: Append[xs, Y] } // 类型本身可正常使用 val x: Append[(String, Int), Long] = ("", 1, 2L) // 以下函数实现编译失败 def append[X <: Tuple, Y](x: X, y: Y): Append[X, Y] = x match case _: EmptyTuple => y *: EmptyTuple case x *: xs => x *: append(xs, y)
编译输出错误:
[E007] Type Mismatch Error: case _: EmptyTuple => y *: EmptyTuple ^^^^^^^^^^^^^^^ Found: Y *: EmptyTuple.type Required: Append[X, Y] where: X is a type in method append with bounds <: Tuple Note: a match type could not be fully reduced: trying to reduce Append[X, Y] failed since selector X does not match case EmptyTuple => Y *: EmptyTuple and cannot be shown to be disjoint from it either. Therefore, reduction cannot advance to the remaining case case x *: xs => x *: Append[xs, Y] longer explanation available when compiling with `-explain` [E007] Type Mismatch Error: case x *: xs => x *: append(xs, y) ^^^^^^^^^^^^^^^^^^ Found: Any *: Append[Tuple, Y] Required: Append[X, Y] where: X is a type in method append with bounds <: Tuple Note: a match type could not be fully reduced: trying to reduce Append[Tuple, Y] failed since selector Tuple does not match case EmptyTuple => Y *: EmptyTuple and cannot be shown to be disjoint from it either. Therefore, reduction cannot advance to the remaining case case x *: xs => x *: Append[xs, Y] longer explanation available when compiling with `-explain`
错误原因
Scala 3的匹配类型归约是编译期操作,普通的运行时模式匹配无法让编译器收窄泛型参数X的具体类型:
- 进入
EmptyTuple分支时,编译器无法证明X = EmptyTuple,因此不能将Append[X, Y]归约为Y *: EmptyTuple - 进入
x *: xs分支时,编译器无法推导xs的精确静态类型,只会将其判定为通用Tuple类型,递归调用的返回值自然无法匹配Append[X, Y]的要求
修复方法
给方法添加inline修饰符,同时使用inline match做编译期模式匹配,让编译器在展开内联代码时完成匹配类型的归约,可正常编译的实现如下:
inline def append[X <: Tuple, Y](x: X, y: Y): Append[X, Y] = inline x match case _: EmptyTuple => y *: EmptyTuple case x *: xs => x *: append(xs, y)
inline标记不可省略,非内联方法无法在编译期完成分支的类型推导,仍然会抛出相同的类型不匹配错误。
内容的提问来源于stack exchange,提问作者Taig
相关产品推荐
相关产品推荐

