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

Scala3的derivings.Mirror无法推导AnyVal值类与opaque类型问题问询

问题1:AnyVal值类/不透明类型的Mirror推导替代方案

除了自定义宏外,有两种更易维护的实现方案:

  • 手动为目标类型导出Mirror实例:在值类/不透明类型的定义作用域内,手动构造符合要求的Mirror对象即可被summonFrom捕获
    示例代码:
    // 值类手动导出Mirror
    case class Bar(value: String) extends AnyVal
    given Mirror.Of[Bar] = Mirror.ProductOf[Bar, Tuple1[String]](
      t => Bar(t.head),
      b => Tuple1(b.value)
    )
    
    // 不透明类型手动导出Mirror
    opaque type Hoo = Long
    object Hoo:
      given Mirror.Of[Hoo] = Mirror.ProductOf[Hoo, Tuple1[Long]](
        t => t.head,
        h => Tuple1(h)
      )
    
  • 用inline匹配直接解析类型结构:无需依赖Mirror,直接通过scala.compiletime包下的erasedValue、constValueTuple等工具,在inline方法中直接匹配值类/不透明类型的底层结构,实现通用派生逻辑。
问题2:继承AnyVal的样例类无法匹配Mirror的原因

这是Scala3的官方设计,不是bug:
Scala3的deriving.Mirror自动推导默认只针对普通乘积类型、和类型生成实例,AnyVal值类的设计核心是零额外包装开销,编译期会尽可能擦除为底层类型。如果自动为值类生成Mirror实例,会导致派生逻辑(比如序列化、编解码)默认把值类处理成嵌套的样例类结构,违背值类的设计初衷,因此官方的自动派生逻辑故意跳过了所有继承AnyVal的类型。

问题3:SummonFrom中检索隐式转换完成推导的可行性

可以实现,但你的示例代码中多态函数的匹配写法不符合Scala3的语法规则,正确写法需要显式捕获转换前的类型参数:

trait Result[A]
inline def derive[A]: Result[A] = summonFrom {
  case x: Result[A] => x
  case conv: Conversion[Result[?], Result[A]] =>
    // 显式匹配捕获转换前的类型t
    inline conv match
      case c: Conversion[Result[t], Result[A]] => c(derive[t])
  case _ => error("Derive failed")
}

上述代码可以正确识别从Result[T]到Result[A]的隐式转换,自动推导T的类型并完成递归调用。

宏与编译期操作的区别说明
  • 编译期操作是Scala3封装的高层编译时能力集合,包括inline方法、scala.compiletime工具包、Mirror派生、summonFrom等,特点是无需操作抽象语法树(AST),代码写法和普通Scala代码一致,类型安全,编译错误提示清晰,适合绝大多数常规派生场景。
  • 宏是更底层的编译期操作,直接操作编译器AST,可实现所有高层编译期操作支持的能力,还能实现高层API覆盖不到的自定义逻辑(比如自定义代码生成、定制类型检查规则),但学习成本高,需要熟悉编译器内部API,不同Scala小版本间API可能不兼容,编译出错时容易出现晦涩的内部错误提示,仅建议在高层API无法满足需求时使用。

内容的提问来源于stack exchange,提问作者giiita

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 15:45:02