Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scalacheck arbitrary with generics

I'm trying to generate an arbitrary list as follows:

scala> def validPairs[T] = Arbitrary.arbitrary[List[(T, Option[T])]] suchThat(!_.isEmpty)
<console>:8: error: could not find implicit value for parameter a: org.scalacheck.Arbitrary[List[(T, Option[T])]]
   def validPairs[T] = Arbitrary.arbitrary[List[(T, Option[T])]] suchThat(!_.isEmpty)

Any idea what I'm doing wrong here? Using a concrete type works without me having to define an implicit parameter.

scala> def validPairsString = Arbitrary.arbitrary[List[(String, Option[String])]] suchThat(!_.isEmpty)
validPairsString: org.scalacheck.Gen[List[(String, Option[String])]]

This is using scala 2.9.2 and scalacheck 1.10.0

Thanks in advance.

like image 350
rubanm Avatar asked Jan 18 '26 05:01

rubanm


2 Answers

I have hit this problem myself, trying to generate generic properties, that can later be instantiated for various concrete types. I found the OP's answer a bit crytpic, so I thought it would be good to provide a more elaborate one. I first repeat OP's answer slowly. Then show that the same applies to writing properties with scalacheck.

The key problem is that the following does not compile (I simplified the problem given by the OP):

def validPair[T] = Arbitrary.arbitrary[(T,T)]

With a modern Scala compiler you get a different error message:

diverging implicit expansion for type org.scalacheck.Arbitrary[(T, T)]
starting with method arbTuple2 in trait ArbitraryArities

(this to help those who Google for this problem today).

It suffices to bound the type parameter by arbitrary (the OP's answer was a bit cryptic on quick reading):

def validPair[T :Arbitrary] = Arbitrary.arbitrary[(T,T)]

Now the same needs to be done if you are defining generic properties. Here is an example of associativity axiom for monoids:

def associative[A :Arbitrary] (m: Monoid[A]) :Prop =
  forAll ( (a1: A, a2: A, a3: A) => m.op(m.op(a1,a2), a3) == m.op(a1,m.op(a2,a3)) )

It yields a similar error without the bound of A to Arbitrary. I hope others starting to write their first generic properties with scalacheck will find this useful.

like image 83
Andrzej Wąsowski Avatar answered Jan 19 '26 18:01

Andrzej Wąsowski


Found the answer on a different list: def validPairs[T : Arbitrary] = ... (Tell it that you will supply a (possibly implicit) way to generate T.)

like image 33
rubanm Avatar answered Jan 19 '26 20:01

rubanm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!