假设我有以下Scala代码:
sealed trait Foo
sealed trait Bar
object Foo1 extends Foo
object Foo2 extends Foo
object Foo3 extends Foo
object Bar1 extends Bar
object Bar2 extends Bar
object Bar3 extends Bar
case class Hello(foo:Foo, bar:Bar)
val a = Hello(Foo1, Bar2) // allowed
val b = Hello(Foo2, Bar2) // suppose not allowed
如果有任何不兼容的组合应用于Hello
,我需要在编译时捕获。假设只允许以下组合:(Foo1, Bar1)
、(Foo1, Bar2)
、(Foo2, Bar3)
和(Foo3, Bar3)
。
是否可以在编译时对此进行测试?我意识到插件和宏可能允许我这样做。如有提示,不胜感激。上面的教程对于Scala(2.11.x)的最新版本来说似乎已经过时了,所以指向其他教程的指针也很棒。
在实际示例中,大约有10个Foo
和Bar
的实例,总共给出了100个组合,其中大约一半是无效的。此外,有效的组合在未来可能会任意变化。
编辑
实际问题有点复杂。Hello
方法接收Seq
如下:
case class Hello(foos:Seq[Foo], bars:Seq[Bar])
复杂标准的例子有:
- 如果
foos
包含Foo1
,则bars
不能具有Bar1
foos
不能同时包含Foo1
和Foo3
代码示例:
Hello(Seq(Foo1), Seq(Bar2, Bar3)) // valid
Hello(Seq(Foo1, Foo3), Seq(Bar1)) // invalid due to rule 2
类型有一个技巧,不确定它是否非常漂亮(一点也不漂亮),你必须手动编写很多这样的规则,但mb你不需要使用大量的插件/libs:
trait Validator[F, S] { }
object Validator {
implicit object firstPair extends Validator[Foo1.type, Bar1.type]
implicit object secondPair extends Validator[Foo1.type, Bar2.type]
implicit object thirdPair extends Validator[Foo2.type, Bar3.type]
implicit object fourthPair extends Validator[Foo3.type, Bar3.type]
}
case class Hello[F <: Foo, S <: Bar](foo: F, bar: S)(implicit v: Validator[F, S])
val a = Hello(Foo1, Bar2) // allowed
val b = Hello(Foo2, Bar2) // break in compile time