如何在 scala 3 中为元组定义 scala.ValueOf?

问题描述 投票:0回答:1

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 scala-3
1个回答
0
投票

类型类和匹配类型是 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)
© www.soinside.com 2019 - 2024. All rights reserved.