scala - Scala:在编译时验证类参数不是 instanceOf 特征
问题描述
在编译时,我想验证类参数不是特定特征 T 的实例。我知道如何在运行时使用require
或 acase match
但想知道如何在编译时完成以防止用户提供某种类型的对象混入。
我已经研究了 scala 宏/反射,但无法完全理解这一点。
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
对于类参数,您可以执行
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)
推荐阅读
- angular - 尝试添加自动映射器的 Visual Studio 角度模板
- flutter - 颤振/飞镖抽象类中的工厂方法
- javascript - 有条件地将数据包装在与 vue 的链接中
- c++ - 单独地,std::getline() 工作正常,但如果事先有输入,则输出行为异常
- autofill - xlwings 和自动填充脚本
- tableau-api - 计算字段影响 Tableau 中的总计
- iis - KB5005043 影响解密 web.config?
- c# - C# VSIX 模板:尝试使用自定义向导会导致程序集引用错误
- kubernetes - 在 minikube 中从 yaml 文件创建部署
- python - For循环和嵌套If语句比较,Python中的简化