5
我是相當新的ScalaCheck(和Scala完全),所以這可能是一個相當簡單的解決方案Scalacheck收縮
我使用ScalaCheck產生用於AST測試和驗證作家/解析器的工作。我有這些文件
AST.scala
package com.test
object Operator extends Enumeration {
val Add, Subtract, Multiply, Divide = Value
}
sealed trait AST
case class Operation(left: AST, op: Operator.Value, right: AST) extends AST
case class Literal(value: Int) extends AST
GenOperation.scala
import com.test.{AST, Literal}
import org.scalacheck._
import Shrink._
import Prop._
import Arbitrary.arbitrary
object GenLiteral extends Properties("AST::Literal") {
property("Verify parse/write") = forAll(genLiteral){ (node) =>
// val string_version = node.writeToString() // AST -> String
// val result = Parse(string_version) // String -> AST
true
}
def genLiteral: Gen[Literal] = for {
value <- arbitrary[Int]
} yield Literal(value)
implicit def shrinkLiteral: Shrink[AST] = Shrink {
case Literal(value) =>
for {
reduced <- shrink(value)
} yield Literal(reduced)
}
}
GenOperation.scala
import com.test.{AST, Operation}
import org.scalacheck._
import Gen._
import Shrink._
import Prop._
import GenLiteral._
object GenOperation extends Properties("AST::Operation") {
property("Verify parse/write") = forAll(genOperation){ (node) =>
// val string_version = node.writeToString() // AST -> String
// val result = Parse(string_version) // String -> AST
true
}
def genOperation: Gen[Operation] = for {
left <- oneOf(genOperation, genLiteral)
right <- oneOf(genOperation, genLiteral)
op <- oneOf(Operator.values.toSeq)
} yield Operation(left,op,right)
implicit def shrinkOperation: Shrink[AST] = Shrink {
case Operation(l,o,r) =>
(
for {
ls <- shrink(l)
rs <- shrink(r)
} yield Operation(ls, o, rs)
) append (
for {
ls <- shrink(l)
} yield Operation(ls, o, r)
) append (
for {
rs <- shrink(r)
} yield Operation(l, o, rs)
) append shrink(l) append shrink(r)
}
}
在示例代碼我寫的(什麼是上面粘貼)我得到的錯誤
ambiguous implicit values:
both method shrinkLiteral in object GenLiteral of type => org.scalacheck.Shrink[com.test.AST]
and method shrinkOperation in object GenOperation of type => org.scalacheck.Shrink[com.test.AST]
match expected type org.scalacheck.Shrink[com.test.AST]
ls <- shrink(l)
我如何寫這個收縮的方法呢?
這正是我所期待的。我猜是一個側面問題,因爲我有三個不同的文件,分別是AST,Operation和Literal,我如何讓Scala識別隱式def? –
你可以將'Literal'和'Operation'含義('Gen'和'Shrink')分成兩個不同的特徵。然後你可以將它們混合成一個'AST'特性並在其中定義一個'收縮[AST]'。需要時,將這些特徵混合在「屬性」對象中。 –
另一種解決方案可能不是依賴implicits並使用'shrinkLiteral(l)'和'shrinkOperation(o)'顯式地定義'shrinkAST'。 –