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
相关产品推荐
相关产品推荐

