Scalacheck 新的可构建实例

Scalacheck new Buildable Instances

我有以下 ScalaCheck 代码。这个想法是使用 Java HashSet 作为容器自动生成整数集。以下代码在几年前可以运行,但现在无法编译。

import java.util.HashSet

import scala.collection._

import org.scalacheck.Properties 
import org.scalacheck.Prop._
import org.scalacheck.util.Buildable

package simpletest {

    class SimpleSpecification extends Properties("Simple") {

        implicit def buildableHashSet[T] : Buildable[T,HashSet[T]] = new Buildable[T, HashSet[T]] {
            def builder = new mutable.Builder[T,HashSet[T]] {
                val al = new HashSet[T]
                def +=(x: T) = {
                    al.add(x)
                    this 
                }
                def clear() = al.clear()
                def result() = al
            }
        } 

        property("simple") = 
            forAll{(a: HashSet[Int]) => 
                a.size() == 1
            }

    }
} 

它现在失败了

...simpletest/SimpleSpecification.scala:26: could not find implicit value for parameter a1: org.scalacheck.Arbitrary[java.util.HashSet[Int]]             
forAll{(a: HashSet[Int]) => 

我广泛搜索了有关使用 Buildable 的说明,但只能在 scalacheck 用户指南中找到一个通过的参考。据我所知,我的用法与 Buildable.scala 中的用法相匹配(用户指南指出)。有没有人知道过去几年发生了什么变化,以及如何更新我的代码以使其再次运行?

forAll() 需要隐式 Arbitrary[HashSet[Int]]。它可以使用 Gen.containerOf() 和隐式 Buildable[T,HashSet[T]]HashSet[T] => Traversable[T].

来定义

代码如下:

package simpletest

import java.util.HashSet

import org.scalacheck.Arbitrary.arbitrary
import org.scalacheck.Prop._
import org.scalacheck.util.Buildable
import org.scalacheck.{Arbitrary, Gen, Properties}

import scala.collection.JavaConverters._
import scala.collection._
import scala.language.implicitConversions


class SimpleSpecification extends Properties("Simple") {

  implicit def buildableHashSet[T]: Buildable[T, HashSet[T]] = new Buildable[T, HashSet[T]] {
    def builder = new mutable.Builder[T, HashSet[T]] {
      val al = new HashSet[T]

      def +=(x: T) = {
        al.add(x)
        this
      }

      def clear() = al.clear()

      def result() = al
    }
  }

  implicit def hashSetTraversable[T](hashSet: HashSet[T]): Traversable[T] = {
    hashSet.asScala
  }

  implicit val intHashSetGen: Arbitrary[HashSet[Int]] =
    Arbitrary(Gen.containerOf[HashSet, Int](arbitrary[Int]))

  property("simple") =
    forAll { (a: HashSet[Int]) =>
      a.size() == 1
    }

}

这是我的最终解决方案。我按照 Kawty 的建议添加了一个从 HashSet[T] 到 Traversable[T] 的隐式函数(但不需要 intHashSetGen)。我还使 SimpleSpecification 成为对象,并使 属性 更有趣。

import java.util.HashSet

import scala.collection._
import scala.collection.JavaConverters._

import org.scalacheck.Properties
import org.scalacheck.Prop._

import org.scalacheck.util.Buildable

package simpletest {

    object SimpleSpecification extends Properties("Simple") {

        implicit def buildableHashSet[T] : Buildable[T,HashSet[T]] = new Buildable[T,HashSet[T]] {
            def builder = new mutable.Builder[T,HashSet[T]] {
                val al = new HashSet[T]
                def +=(x: T) = {
                    al.add(x)
                    this
                }
                def clear() = al.clear()
                def result() = al
            }
        }

        implicit def traverseHashSet[T](s : HashSet[T]) : Traversable[T] = s.asScala

        property("simple") = 
            forAll{(a: HashSet[Int]) => 
                a.size() < 2
            }
    }
}