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

Scala 3中为不透明类型推导类型类实例的方法问询

Scala 3中opaque类型别名与derives关键字的结合问题

Scala 3目前不支持在opaque type定义后直接使用derives关键字。原因在于derives是为case class、enum这类编译器会生成类结构的类型设计的,它依赖编译器生成的合成类来派生类型类实例;而opaque类型别名只是对底层类型的封装,没有额外的类结构,编译器无法通过derives自动关联底层类型的现有类型类实例。

不过你可以用更简洁的方式实现无样板的类型类实例推导,不用手动复制底层实例:

方案1:利用inline given和类型约束

trait Show[T]:
  def show(t: T): String

object Show:
  given Show[Int] = (i: Int) => s"Int($i)"

opaque type Id = Int
object Id:
  // 直接复用底层类型的Show实例
  inline given Show[Id] = summon[Show[Int]].asInstanceOf[Show[Id]]

// 验证
val myId: Id = 123
println(summon[Show[Id]].show(myId)) // 输出 Int(123)

方案2:通用派生工具方法

如果需要给多个opaque类型复用逻辑,可以封装一个通用方法:

trait Show[T]:
  def show(t: T): String

object Show:
  given Show[Int] = (i: Int) => s"Int($i)"
  given Show[String] = (s: String) => s"String($s)"

// 通用工具,自动复用底层类型的Show实例
object OpaqueDerivations:
  inline def deriveShow[Opaque, Underlying](using 
    showUnderlying: Show[Underlying],
    ev: Opaque =:= Underlying
  ): Show[Opaque] = showUnderlying.asInstanceOf[Show[Opaque]]

// 使用示例
opaque type Id = Int
object Id:
  given Show[Id] = OpaqueDerivations.deriveShow[Id, Int]

opaque type Username = String
object Username:
  given Show[Username] = OpaqueDerivations.deriveShow[Username, String]

这两种方式都能达到你想要的“无样板、自动复用底层类型实例”的效果,同时保留opaque类型的封装特性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:20:31