You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 05:21:22