【问题标题】:How to limit class type parameter with specific tuples? (Scala 2.10.4)如何使用特定元组限制类类型参数? (斯卡拉 2.10.4)
【发布时间】:2015-01-26 20:37:02
【问题描述】:

我想将类型 [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])。因此,我确实希望有一种访问类类型参数的方法。

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 等进行子类型化不是很好。

【问题讨论】:

  • 您能解释一下您的用例吗?不清楚(对我来说,无论如何)你在问什么。
  • @Paul trait QV_Storable 必须只接受特定类型的元组。例如 (Int, String) 或 (Int, Int, Int)。如果我要限制类型 [R <: product>
  • 这不是您的用例,只是再次提出的问题。但也许只有我无法立即看到你想要这个的原因。
  • @Paul,在我的情况下,我想确保通过 trait 的所有值都可以插入到特定表或具有传统数据结构的存储中。

标签: scala templates tuples


【解决方案1】:

你可以提供一个类型类,它只有足够的元组实现:

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 "}

【讨论】:

  • 奥列格,感谢您的回答。我尝试了第一种方法,但无法使其按预期工作。可能我做错了什么。你介意看看吗?我已经编辑了你的答案。
  • @CronAcronis 在第一个版本中,您可以用错误的R 声明QV_Storable[R] 的类型,但您不能调用method .第二个版本你不能甚至声明无效类型,但你需要明确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-11
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 2021-08-10
  • 1970-01-01
相关资源
最近更新 更多