Scala:在编译时验证 class 参数不是 instanceOf 特征
Scala: verify class parameter is not instanceOf a trait at compile time
在编译时我想验证 class 参数不是特定特征 T 的实例。我知道如何在运行时使用 require
或 case match
但想知道如何在编译时完成此操作以防止用户提供特定类型的对象混合。
我研究过 scala macros/reflection 但无法完全理解它。
trait A
trait B
trait T
abstract class C extends A with B
case class P(c: C){
require(!c.isInstanceOf[T]) // how to do this at compile time ?
}
// usage as below
object c1 extends C
object c2 extends C
object c3 extends C
object c4 extends C with T
val l = List(c1, c2, c3, c4).map(k => P(k)) // should fail at compile time
您无法使用 List
执行此操作。 List(c1, c2, c3, c4)
中的所有元素都属于同一类型,即 C
,并且其中之一的类型为 C with T
的信息将丢失。
new C {}
、new C with T {}
是 c1, c2, c3, c4
的运行时值,编译器在编译 List(c1, c2, c3, c4)
.
时无法访问它们
您可以使用 HList
执行此操作。使用 shapeless.<:!<
、shapeless.ops.hlist.LiftAll
和 kind-projector
def noElementIsSubtypeOfT[L <: HList](l: L)(implicit liftAll: LiftAll[* <:!< T, L]) = null
noElementIsSubtypeOfT(c1 :: c2 :: c3 :: HNil) // compiles
// noElementIsSubtypeOfT(c1 :: c2 :: c3 :: c4 :: HNil) // doesn't compile
或
def noElementIsSubtypeOfT[L <: HList : LiftAll[* <:!< T, *]](l: L) = null
对于class参数你可以做
case class P[U <: C](c: U)(implicit ev: U <:!< T)
P(c1) // compiles
P(c2) // compiles
P(c3) // compiles
// P(c4) // doesn't compile
或
case class P[U <: C : * <:!< T](c: U)
在编译时我想验证 class 参数不是特定特征 T 的实例。我知道如何在运行时使用 require
或 case match
但想知道如何在编译时完成此操作以防止用户提供特定类型的对象混合。
我研究过 scala macros/reflection 但无法完全理解它。
trait A
trait B
trait T
abstract class C extends A with B
case class P(c: C){
require(!c.isInstanceOf[T]) // how to do this at compile time ?
}
// usage as below
object c1 extends C
object c2 extends C
object c3 extends C
object c4 extends C with T
val l = List(c1, c2, c3, c4).map(k => P(k)) // should fail at compile time
您无法使用 List
执行此操作。 List(c1, c2, c3, c4)
中的所有元素都属于同一类型,即 C
,并且其中之一的类型为 C with T
的信息将丢失。
new C {}
、new C with T {}
是 c1, c2, c3, c4
的运行时值,编译器在编译 List(c1, c2, c3, c4)
.
您可以使用 HList
执行此操作。使用 shapeless.<:!<
、shapeless.ops.hlist.LiftAll
和 kind-projector
def noElementIsSubtypeOfT[L <: HList](l: L)(implicit liftAll: LiftAll[* <:!< T, L]) = null
noElementIsSubtypeOfT(c1 :: c2 :: c3 :: HNil) // compiles
// noElementIsSubtypeOfT(c1 :: c2 :: c3 :: c4 :: HNil) // doesn't compile
或
def noElementIsSubtypeOfT[L <: HList : LiftAll[* <:!< T, *]](l: L) = null
对于class参数你可以做
case class P[U <: C](c: U)(implicit ev: U <:!< T)
P(c1) // compiles
P(c2) // compiles
P(c3) // compiles
// P(c4) // doesn't compile
或
case class P[U <: C : * <:!< T](c: U)