ValueOf
类型函数可以在方法的上下文参数列表中使用来选择单例类型的单个居民,如果类型参数不是单例,则会引发编译错误。
enum Color { case red, green, blue }
def singleInhabitantOf[T](using holder: ValueOf[T]): T = holder.value
println(singleInhabitantOf[Color.red.type] == Color.red) // outputs true
但它是有限的。它不适用于组件类型均为单例的元组。
singleInhabitantOf[(Color.red.type, Color.blue.type)] // compile error
错误消息为: 没有可用于 (Color.red, Color.blue) 的单例值;用于
ValueOf
合成的合格单例类型包括文字和稳定路径。
所以我尝试以这种方式为元组创建一个版本:
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 // a tuple mapping is missing here but how to implement it is another question.
singleInhabitantsOf[(Color.red.type, Color.blue.type)] // Copile error
不幸的是,编译器抱怨说:没有为参数持有者找到类型 ValuesOf[(Color.red, Color.blue)] 的给定实例。 显然,它在隐式上下文中查找元组实例,而不是用单例实例合成元组。
但是
implicitly[summonAll[ValuesOf[T]]]
编译并运行良好。 所以我可以像这样使用
summonAll
重写该方法
inline def singleInhabitantsOf2[T <: Tuple]: Tuple = summonAll[ValuesOf[T]]
但是这个解决方案对我的最终目的没有用,为此,单例性检查应该在方法签名中,这样如果出现错误,编译器就不会开始处理主体。
关于如何定义与上下文参数列表中的元组一起使用的 ValueOf 有什么想法吗?
类型类和匹配类型是 Scala 3 中执行类型级计算的两种方法(如 Scala 2 中的类型投影和类型类、Haskell 中的类型族和类型类)。
混合类型类和匹配类型可能很棘手。
您似乎想要类型类而不是匹配类型
trait ValuesOf[T <: Tuple]:
def value: T
object ValuesOf:
given ValuesOf[EmptyTuple] with
val value = EmptyTuple
given [h, t <: Tuple](using vh: ValueOf[h], vt: ValuesOf[t]): ValuesOf[h *: t] with
val value = vh.value *: vt.value
def singleInhabitantsOf[T <: Tuple](using holder: ValuesOf[T]): T = holder.value
singleInhabitantsOf[(Color.red.type, Color.blue.type)] // (red,blue)