Scalacheck shrink

I'm new to ScalaCheck (and Scala completely), so this might be a pretty simple solution.

I use ScalaCheck to create tests for the AST and verify the author / parser. I have these files

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) } } 

In the example code that I wrote (which is inserted above), I get an error

 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) 

How do I write shrink methods for this?

+5
source share
1 answer

You have two implicit instances of Shrink[AST] , so the compiler complains about ambiguous implicit values.

You can rewrite the code as follows:

 implicit def shrinkLiteral: Shrink[Literal] = Shrink { case Literal(value) => shrink(value).map(Literal) } implicit def shrinkOperation: Shrink[Operation] = Shrink { case Operation(l,o,r) => shrink(l).map(Operation(_, o, r)) append shrink(r).map(Operation(l, o, _)) append ??? } implicit def shrinkAST: Shrink[AST] = Shrink { case o: Operation => shrink(o) case l: Literal => shrink(l) } 
+4
source

Source: https://habr.com/ru/post/1264991/


All Articles