8

我想生成一个整数列表,该列表对应于ScalaCheck.

    import org.scalacheck._
    import Arbitrary.arbitrary

    val smallInt = Gen.choose(0,10)
    val bigInt = Gen.choose(1000, 1000000)
    val zeroOrOneInt = Gen.choose(0, 1)
    val smallEvenInt = smallInt suchThat (_ % 2 == 0)

    val gens = List(smallInt, bigInt, zeroOrOneInt, smallEvenInt)
    //val listGen: Gen[Int] = ??
    //println(listGen.sample) //should print something like List(2, 2000, 0, 6)

对于给定的gens,我想创建一个生成器listGen,其有效样本可以是List(2, 2000, 0, 6)。这是我第一次尝试使用元组。

    val gensTuple = (smallInt, bigInt, zeroOrOneInt, smallEvenInt)
    val tupleGen = for {
        a <- gensTuple._1
        b <- gensTuple._2
        c <- gensTuple._3
        d <- gensTuple._4
    } yield (a, b, c, d)

    println(tupleGen.sample) // prints Some((1,318091,0,6))

这可行,但我不想使用元组,因为生成器列表gens是动态创建的,并且列表的大小不是固定的。有没有办法用列表做到这一点?

我希望listGen在 scalacheckforAll属性检查中使用 list() 的生成器。

这看起来像是一个玩具问题,但这是我能做的最好的事情,以创建一个独立的片段来重现我面临的实际问题。

4

4 回答 4

14

使用Gen.sequence方法怎么样?它将 a 转换Iterable[Gen[T]]为 a Gen[C[T]],其中C可以是List

  def sequence[C[_],T](gs: Iterable[Gen[T]])(implicit b: Buildable[T,C]): Gen[C[T]] = 
     ...
于 2012-11-25T10:56:37.153 回答
3

只需使用,但要小心,因为如果您没有完全参数化它(错误Gen.sequence,它会尝试返回 a 。java.util.ArrayList[T]

完整的工作示例:

def genIntList(): Gen[List[Int]] = {

  val gens = List(Gen.chooseNum(1, 2), Gen.chooseNum(3, 4))

  Gen.sequence[List[Int], Int](gens)
}

println(genIntList.sample.get) // prints: List(1,4)
于 2017-01-05T04:09:02.320 回答
1

编辑:请忽略,这不能回答提问者的问题


我还不能对帖子发表评论,所以我不得不在这里冒险猜测一下。我认为函数“样本”适用于生成器

你不能这样做的任何理由:

gens map (t=>t.sample)
于 2012-11-25T10:16:10.520 回答
0

对于更理论的答案:您想要的方法是traverse,这相当于sequence compose map虽然它可能更有效。它的一般形式是:

def traverse[C[_]: Traverse, F[_]: Applicative, A, B](f: A => F[B], t: C[A]): F[C[B]]

它的行为类似于map但允许您在遍历期间携带一些额外的Applicative结构,并沿途对其进行排序。

于 2012-12-20T20:11:20.843 回答