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

问题描述

我有一个带有2个类型参数的案例类

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

类型T显然是类属性“模型”的一种。 RT类型可以与T相同,也可以为List [T](取决于我们创建的OnetoOne或OnetoMany关系类型)。因此,我如何限制RT,使其不允许传递T或List [T]以外的其他内容

PS我正在阅读有关协方差 contravariance 的信息,但了解得并不多。在我的情况下适用吗?如果是,请提供一个例子。如果不是,请显示其他工具以达到目的。我什至不明白T和List [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$29$Model@51c26394)

scala> Relation[Model,List[Model]](v)
val res16: Relation[Model,List[Model]] = Relation(rs$line$29$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$2 of method apply in object Relation
,

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

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

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)?