T 和 List[T] 的类型参数边界

Type parameter bounding for T and List[T]

我有一个案例 class 有 2 个类型参数

case class Relation[T <: Model, RT] (model: T) 

类型 T 显然是 class 属性 'model' 的类型。类型 RT 可以与 T 相同,也可以是 List[T](取决于我们创建的关系类型是 OneToOne 还是 OneToMany)。那么我如何限制 RT,它不允许传递除 T 或 List[T] 之外的其他内容。

PS 我正在阅读有关 covariancecontravariance 的内容,但了解不多。它适用于我的情况吗?如果是,能否请您举个例子。如果没有 - 那么请展示其他工具来达到它。我什至无法理解 T 和 List[T] 之间的关系? T <: 列表[T] 或列表[T] <: T?

提前致谢

在 Scala 3 中,您可以使用具有广义约束的联合类型

case class Relation[T <: Model, RT](model: T)(using (RT =:= T) | (RT =:= List[T]))

例如

scala> class Model
     | case class Relation[T <: Model, RT](model: T)(using (RT =:= T) | (RT =:= List[T]))
// defined class Model
// defined case class Relation

scala> val v = new Model
val v: Model = Model@51c26394

scala> Relation(v)
val res15: Relation[Model, Model] = Relation(rs$line$Model@51c26394)

scala> Relation[Model, List[Model]](v)
val res16: Relation[Model, List[Model]] = Relation(rs$line$Model@51c26394)

scala> Relation[Model, 42](v)
1 |Relation[Model, 42](v)
  |                      ^
  |no implicit argument of type (42 : Int) =:= Model | (42 : Int) =:= List[Model] was found for parameter x of method apply in object Relation

考虑 T <: List[T]List[T] <: T 和协方差,您正在尝试使用 OOP/subtype 多态性来解决您的问题。

在 Scala 2 中,您可以尝试一种类型 class(即席多态性)

case class Relation[T <: Model, RT](model: T)(implicit sel: Selector[T, RT])

trait Selector[T <: Model, RT]
object Selector {
  implicit def single[T <: Model]: Selector[T, T] = null
  implicit def multiple[T <: Model]: Selector[T, List[T]] = null
}

How to define "type disjunction" (union types)?