是否可以将泛型参数限制为超类型的子集



在 Scala 中,我可以将泛型参数限制为超类型的子集吗?

sealed trait A
class X extends A
class Y extends A
class Z extends A
def myStrictFunc[T is X or Y, but not Z](o: T)
                 ----------+----------
                           |
                           Can I have this constraint in Scala ?

如果您需要排除众多中的一个,Dmytro Mitin的答案是一个很好的答案。另一方面,如果您需要将包容性限制在众多中的少数几个,这里有一种方法可以做到这一点。

sealed trait A {val id: Int}
class W extends A {val id = 13}
class X extends A {val id = 17}
class Y extends A {val id = 18}
class Z extends A {val id = 21}
trait Contra[-X]
type Union[A,B] = {
  type Check[Z] = Contra[Contra[Z]] <:< Contra[Contra[A] with Contra[B]]
}
def myStrictFunc[T <: A : Union[X,Y]#Check](t: T): Int = t.id
myStrictFunc(new X)  //res0: Int = 17
myStrictFunc(new Y)  //res1: Int = 18
myStrictFunc(new Z)  //won't compile
myStrictFunc(new W)  //won't compile

Union 类型可以扩展到 3、4 或更多类型,但代码有点冗长。

是的,你可以。例如,使用无形状

import shapeless.=:!=
sealed trait A
class X extends A
class Y extends A
class Z extends A
def myStrictFunc[T <: A](o: T)(implicit ev: T =:!= Z) = ???

否则,您可以手动实现=:!=

强制实施类型差异

使用Shapeless可能是目前最简单的方法,但是,您可能需要检查Dotty,这是下一代Scala编译器,具有内置的Union类型。

最新更新