Scala:在编译时验证类参数不是 instanceOf 特征 [英] Scala: verify class parameter is not instanceOf a trait at compile time
问题描述
在编译时我想验证一个类参数不是特定特征 T 的实例.我知道如何在运行时使用 require
或 case match代码>,但想知道如何在编译时做到这一点,以防止用户提供某些类型的对象混合.
At compile time I want to verify that a class parameter is NOT an instance of a particular trait T. I know how to do it at runtime using require
or a case match
but wondering how this might be done at compile to prevent users from providing certain type of object mixins.
我已经研究了 Scala 宏/反射,但无法完全解决这个问题.
I've looked into scala macros/reflection but not able to wrap my head around that completely.
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 和 T<的信息/code> 将会丢失.
You can't do this with List
. All elements in List(c1, c2, c3, c4)
will be of the same type i.e. C
and information that one of them has type C with T
will be lost.
new C {}
, new C with T {}
是 c1, c2, c3, c4
的运行时值,编译器没有'在编译 List(c1, c2, c3, c4)
时不能访问它们.
new C {}
, new C with T {}
are runtime values of c1, c2, c3, c4
, compiler doesn't have access to them while compiling List(c1, c2, c3, c4)
.
你可以用 HList
做到这一点.使用 shapeless.<:!<
、shapeless.ops.hlist.LiftAll
和 kind-projector
You can do this with HList
. Using shapeless.<:!<
, shapeless.ops.hlist.LiftAll
and 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
对于类参数你可以做
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)
这篇关于Scala:在编译时验证类参数不是 instanceOf 特征的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!