在编译时,我想验证类参数不是特定特征T的示例。我知道如何在运行时使用require
或case 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
1条答案
按热度按时间pwuypxnk1#
使用
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投影仪或
对于类参数,您可以这样做
或
实际上,有一种方法可以用List修复代码。您可以将类
P
设置为隐式(因此您定义了隐式转换)并指定列表List[P[_]](...)
的类型(所谓的磁体模式12345 6 7,P
是磁体)