【问题标题】:Add custom compile time checks to Scala向 Scala 添加自定义编译时检查
【发布时间】:2015-03-31 05:24:32
【问题描述】:

假设我有以下 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)

是否可以在编译时进行测试? 我意识到pluginsmacros 可能允许我这样做。一些提示将不胜感激。上面的教程对于最新版本的 Scala (2.11.x) 来说似乎已经过时了,所以指向其他教程的指针也很好。

在真实的例子中,FooBar的实例大约有10个,一共给出了100个组合,其中大约一半是无效的。此外,有效组合将来可能会任意更改。

编辑

实际问题要复杂一些。 Hello 方法接受Seq 如下:

case class Hello(foos:Seq[Foo], bars:Seq[Bar]) 

复杂标准的示例如下:

  1. 如果foos 包含Foo1,则bars 不能有Bar1
  2. foos 不能同时包含 Foo1Foo3

代码示例:

Hello(Seq(Foo1), Seq(Bar2, Bar3)) // valid 
Hello(Seq(Foo1, Foo3), Seq(Bar1)) // invalid due to rule 2

【问题讨论】:

  • 除了@DaunnC 的回答,还有对技术here 的解释。
  • 是否有任何规则可以确定哪些组合有效哪些无效?
  • @MilesSabin 否。有效的组合是相当随意的.. 但有一定的规则.. 见我上面的编辑。
  • 你知道编译时那些序列的内容吗? IE。你能将它们表示为元组而不是Seqs 吗?
  • 更新看起来很有帮助,但是,第二行的注释看起来不正确:满足规则 2,不满足规则 1。

标签: scala scala-2.10 scala-2.11


【解决方案1】:

类型有一个技巧,不确定是不是很漂亮(一点也不漂亮),而且你必须手动编写很多这样的规则,但是你不需要使用繁重的插件/库:

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

【讨论】:

  • 这绝对是正确的方法......对于在一流的 Scala 中具有直接解决方案的东西使用宏或插件是完全不合适的。
  • 它也没有那么难看。似乎是最简单的方法。
  • 但是,我想为此使用插件。实际情况比较复杂,因为FooBar本身是由其他类型组成的,而Hello类以数组为参数。
  • 然后发布一个更准确地反映您的问题的示例。宏和插件是最后的解决方案。
  • @Miles Sabin 我已经修改了我的示例
猜你喜欢
  • 2023-03-31
  • 2010-12-28
  • 1970-01-01
  • 2014-04-12
  • 1970-01-01
  • 2021-05-23
  • 1970-01-01
  • 2023-02-07
  • 1970-01-01
相关资源
最近更新 更多