scalacheck icon indicating copy to clipboard operation
scalacheck copied to clipboard

Gen.sequence seems to forget that ScalaCheck is a Scala lib (1.12.1)

Open devmage opened this issue 10 years ago • 4 comments

Consider the following console session, with ScalaCheck 1.12.1:

scala> import org.scalacheck.Gen
import org.scalacheck.Gen

scala> import org.scalacheck.Arbitrary._
import org.scalacheck.Arbitrary._

scala> val genInts = Gen.nonEmptyListOf(arbitrary[Int])
genInts: org.scalacheck.Gen[List[Int]] = org.scalacheck.Gen$$anon$2@393c86dd

scala> case class Bar(str: String, i: Int)
defined class Bar

scala> def genBarWith(i: Int) = for { str <- arbitrary[String] } yield Bar(str, i)
genBarWith: (i: Int)org.scalacheck.Gen[Bar]

scala> val genBarList = for { ints <- genInts; bars <- Gen.sequence { ints.map(genBarWith) } } yield bars
genBarList: org.scalacheck.Gen[java.util.ArrayList[Bar]] = org.scalacheck.Gen$$anon$6@2d97c1a

scala> val genBarList2 = for { ints <- genInts; bars <- Gen.sequence[List[Bar], Bar] { ints.map(genBarWith) } } yield bars
genBarList2: org.scalacheck.Gen[List[Bar]] = org.scalacheck.Gen$$anon$6@57b19137

Incidentally, the type parameters on genBarList2 cause IntelliJ to refuse to compile, although sbt and the REPL are fine with it.

To get back to Scala-land, I have to import scala.collection.JavaConverters._ and map on the generator with .map(_.asScala.toList).

Happy New Year! :smiley:

devmage avatar Jan 14 '15 05:01 devmage

Stumbled on this. It's very annoying.

douglaz avatar May 25 '15 21:05 douglaz

It actually is very aware that it is Scala, and that Scala is not very good at type-inference. For some reason Scala infers the type j.u.List.

As usual in Scala, some judicious use of explicit type parameters solves the day. The first parameter is the fully specified container, and the second is the element type:

scala> val genBarList = for { ints <- genInts; bars <- Gen.sequence[List[Bar], Bar] { ints.map(genBarWith) } } yield bars genBarList: org.scalacheck.Gen[List[Bar]] = org.scalacheck.Gen$$anon$6@36ffdb7f

cheers, jed.

On 26 May 2015 at 07:32, Allan Douglas R. de Oliveira < [email protected]> wrote:

Stumbled on this. It's very annoying.

— Reply to this email directly or view it on GitHub https://github.com/rickynils/scalacheck/issues/131#issuecomment-105321385 .

jedws avatar May 25 '15 23:05 jedws

@jedws in my example above, I offer exactly your proposed solution in genBarList2, so thank you for confirming the behavior on your side. :)

The point here, however, is that without explicit type parameters the resultant List[A] is a java.util.ArrayList[A] instead of a scala.collection.immutable.List[A]. It figures out the A just fine; I'm accustomed to this being a problem, rather than the collection type.

One would think that a Scala library method would try to infer first to Scala types, e.g. here Scala collections. Instead, we see that Gen.sequence seems to infer first to a Java collection. Small annoyance, but it exists.

devmage avatar May 26 '15 18:05 devmage

@devmage sorry, didn't see your solution

Unfortunately, Scala's type inference is not very good. It is often necessary to explicitly annotate in places where it seems silly and that the compiler should do a better job of it.

Could scalacheck have a better signature, or provide a better default Buildable? It probably can! That would be a great PR.

jedws avatar May 27 '15 00:05 jedws