如何用特定元组限制 class 类型参数? (斯卡拉 2.10.4)

How to limit class type parameter with specific tuples? (Scala 2.10.4)

我想将类型 [R] 限制为仅在某处列出的特定元组。我的主要目标是:如果将任何其他元组而不是预期的元组传递给以下特征,确保编译器引发错误。

trait QV_Storable[R <: QV_Cue] {
    val prefix: String
    val tableName = prefix.concat(Random.alphanumeric take 8 mkString)
    def Make(rows: Iterable[R.storageColumns]): String 
}

那么我希望 QV_Storable 只接受 SegmentCue 中列出的元组,因为它是 QV_Cue 的子组。请注意,我将 R.storageColumns 传递给了 Make(rows: Iterable[R.storageColumns])。因此,我确实希望有一种方法来访问 class 类型的参数。

trait QV_Cue{
    type storageColumns <: Product
    type metaColumns <: Product
}
object SegmentCue extends QV_Cue {
    type storageCols = (CoreDataID, String)
    type metaCols = (Int, String, Date, Int)
}

有没有这样限制的? 从 Tuple1、Tuple3 等进行子类型不是很好

您可以提供一个类型 class,只有足够的元组才能实现:

trait Ok[T] {}

// (Int, Int) is Ok
implicit val tupleIntIntOk: Ok[(Int, Int)] = new Ok[(Int, Int)] {}

// (String, _) is Ok too
implicit def tupleStringAOk[A]: Ok[(String, A)] = new Ok[(String, A)] {}

trait QV_Storable[R] {
  def method(implicit rok: Ok[R]): Unit
  // ...
}

在这种情况下,如果作用域中没有 rok 正确类型的值,则无法调用 QV_Storable.method

通过这种方式,您可以使用任何 R 创建 QV_Storable,但如果没有正确的 Ok.

,则无法实际使用任何

有点不同的方法是在类型级别上使用类似的技巧。然而没有隐含的解决方案:

sealed trait Ok[T] {}

case class TupleIntIntOk() extends Ok[(Int, Int)]
case class TupleStringAOk[A]() extends Ok[(String, A)]

trait QV_Storable[R, OkR <: Ok[R]] {
  val prefix: String
  // ...
}

// compiles
val foo = new QV_Storable[(Int, Int), TupleIntIntOk] { val prefix = "xy" }

// doesn't
val bar = new QV_Storable[(Int, String), /* nothing to put here */] { val prefix = "bar "}