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

Scala 3中如何为元组定义可用于上下文参数的ValueOf?

实现支持元组的上下文参数版ValueOf

问题背景

ValueOf类型类可以在方法的上下文参数中获取单例类型的唯一实例,非单例类型会被编译器直接拒绝:

enum Color { case red, green, blue }
def singleInhabitantOf[T](using holder: ValueOf[T]): T = holder.value
println(singleInhabitantOf[Color.red.type] == Color.red) // 输出 true

但它存在局限——无法处理所有元素均为单例类型的元组,比如以下代码会编译失败:

singleInhabitantsOf[(Color.red.type, Color.blue.type)] // 编译错误

错误信息:No singleton value available for (Color.red, Color.blue); eligible singleton types for ValueOf synthesis include literals and stable paths.

尝试自定义ValuesOf类型别名适配元组,但编译器无法自动合成对应的上下文实例:

import scala.Tuple

type ValuesOf[T <: Tuple] <: Tuple = T match {
    case EmptyTuple => EmptyTuple
    case h *: t => ValueOf[h] *: ValuesOf[t]
}

def singleInhabitantsOf[T <: Tuple](using holder: ValuesOf[T]): Tuple = holder
singleInhabitantsOf[(Color.red.type, Color.blue.type)] // 编译错误:找不到ValuesOf类型的given实例

虽然summonAll[ValuesOf[(Color.red.type, Color.blue.type)]]可以正常运行,但用它实现的方法无法在签名阶段完成单例性检查,不符合需求。

解决方案

我们需要定义一个递归的类型类,并为元组的不同情况提供自动合成的given实例,这样就能在上下文参数中完成类型检查:

import scala.Tuple

// 定义支持元组的类型类
trait TupleValueOf[T <: Tuple] {
  def value: Tuple
}

object TupleValueOf {
  // 为空元组提供实例
  given emptyTupleValueOf: TupleValueOf[EmptyTuple] with {
    override def value: EmptyTuple = EmptyTuple
  }

  // 为非空元组递归合成实例:头部元素有ValueOf,尾部有TupleValueOf
  given nonEmptyTupleValueOf[H, T <: Tuple](
    using headValue: ValueOf[H],
    tailValue: TupleValueOf[T]
  ): TupleValueOf[H *: T] with {
    override def value: Tuple = headValue.value *: tailValue.value
  }
}

// 使用该类型类的方法
def singleInhabitantsOf[T <: Tuple](using tv: TupleValueOf[T]): Tuple = tv.value

现在测试代码可以正常编译运行:

enum Color { case red, green, blue }
println(singleInhabitantsOf[(Color.red.type, Color.blue.type)]) // 输出 (red,blue)

如果传入包含非单例类型的元组,编译器会直接报错,满足签名阶段检查的需求:

singleInhabitantsOf[(Color, Color.blue.type)] // 编译错误:无法找到ValueOf[Color]的given实例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:37:35