Scala:在编译时验证类参数不是 instanceOf 特征 [英] Scala: verify class parameter is not instanceOf a trait at compile time

查看:48
本文介绍了Scala:在编译时验证类参数不是 instanceOf 特征的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在编译时我想验证一个类参数不是特定特征 T 的实例.我知道如何在运行时使用 requirecase 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆