Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
devmage opened this issue Jan 14, 2015 · 4 comments
Open

Comments

@devmage
Copy link

devmage commented Jan 14, 2015

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! 😃

@douglaz
Copy link

douglaz commented May 25, 2015

Stumbled on this. It's very annoying.

@jedws
Copy link

jedws commented May 25, 2015

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 <
notifications@github.com> wrote:

Stumbled on this. It's very annoying.


Reply to this email directly or view it on GitHub
#131 (comment)
.

@devmage
Copy link
Author

devmage commented May 26, 2015

@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.

@jedws
Copy link

jedws commented May 27, 2015

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants