Scalacheck set-size 数组生成器
Scalacheck set-size Array Generators
我正在尝试制作一个 ScalaCheck 矩阵生成器,它将生成指定顺序的二维数组/矩阵 (size/dim)。我从教程中的示例开始,并将其简化(用于原型设计——我知道我应该使用 sized 来调整未来生成器的大小)到
def matrix[ T ]( g: Gen[ T ] )( order: Int ): Gen[ Array[ Seq[ T ] ] ] =
Gen.listOfN( order, Gen.listOfN( order, g ) ).map(_.toArray)
但是,如果不放入 ClassTag,我无法从中获取 Array[Array[T]]:
def matrix[ T : ClassTag]( g: Gen[ T ] )( order: Int ): Gen[ Array[ Seq[ T ] ] ] =
Gen.listOfN( order, Gen.listOfN( order, g ) ).map(_.toArray)
我有点理解——我在 Scala 方面经验不足。在到达那里的过程中,我尝试了这个:
def matrix2[ T : ClassTag]( g: Gen[ T ] )( order: Int ): Gen[ Array[ Array[ T ] ] ] =
for {
rowSeq <- Gen.listOfN( order, g )
rowArray <- rowSeq.toArray
seqOfRowArrays <- Gen.listOfN( order, rowArray)
matrix <- seqOfRowArrays.toArray
} yield matrix
但编译器抱怨
"type mismatch; found : Array[T] required: org.scalacheck.Gen[Array[Array[T]]]"
在 rowArray 行和
“这条线有多个标记
- 类型不匹配;找到:org.scalacheck.Gen[Array[T]] 要求:scala.collection.GenTraversableOnce[?]"
在 seqOfRowArrays 行。
我的问题是:
1. 有没有更简单的方法来获得定义大小的数组[Array[T]],即一些绑定任意的方法?
2.上面的for expression的输入有什么问题?
3. 当测试失败时,如何让ScalaCheck在收缩过程中不减少顺序?
#1:不用担心 Arbitrary
v. Gen
。他们基本上是一样的。这里有一个很好的答案来解释它们之间的区别:
#2 你正在混合你的 monadic 容器(Gen
和 Array
),而 scala 正在尽最大努力将它们组合起来,这会给你一个令人困惑的错误。
要修复您的类型错误,请执行此操作
def matrix2[ T : ClassTag]( g: Gen[ T ] )( order: Int ): Gen[ Array[ Array[ T ] ] ] =
for {
rowSeq <- Gen.listOfN( order, g )
rowArray = rowSeq.toArray
seqOfRowArrays <- Gen.listOfN( order, rowArray)
} yield seqOfRowArrays.toArray
如果你在终端中运行这个你会发现一些奇怪的东西:
scala> matrix2(Gen.choose(1,10))(3)
res2: org.scalacheck.Gen[Array[Array[Int]]] = org.scalacheck.Gen$$anon@4c93778e
scala> res2.sample
res3: Option[Array[Array[Int]]] = Some([[I@1dd38904)
scala> res3.foreach{a2 => a2.foreach{a => a.foreach{i => println(s" $i")}; println("\n")}}
6
10
5
6
10
5
6
10
5
这只会生成一行,然后在整个矩阵中重复这一行。我对此的解决方案是使用 scalacheck 生成 order^2 元素,然后在事后将它们分组到您的 2D 数组结构中。这是我的 Scala REPL 中的 copy/paste,我在其中执行此操作:
scala> :paste
// Entering paste mode (ctrl-D to finish)
def matrix2[T: ClassTag](g: Gen[T])(order: Int): Gen[Array[Array[T]]] =
Gen.listOfN(order*order, g).map { squareList =>
squareList.toArray.grouped(order).toArray
}
// Exiting paste mode, now interpreting.
matrix2: [T](g: org.scalacheck.Gen[T])(order: Int)(implicit evidence: scala.reflect.ClassTag[T])org.scalacheck.Gen[Array[Array[T]]]
scala> matrix2(Gen.choose(1,10))(3)
res5: org.scalacheck.Gen[Array[Array[Int]]] = org.scalacheck.Gen$$anon@7519bc73
scala> res5.sample.foreach{a2 => a2.foreach{a => a.foreach{i => println(s" $i")}; println("\n")}}
1
9
9
7
6
10
10
2
6
#3 此生成器的 order
不会更改,因为您使用的是固定集合大小的 listOfN
方法。用户指南中的示例仅调整大小,因为它使用了 Gen.sized
生成器。
我正在尝试制作一个 ScalaCheck 矩阵生成器,它将生成指定顺序的二维数组/矩阵 (size/dim)。我从教程中的示例开始,并将其简化(用于原型设计——我知道我应该使用 sized 来调整未来生成器的大小)到
def matrix[ T ]( g: Gen[ T ] )( order: Int ): Gen[ Array[ Seq[ T ] ] ] =
Gen.listOfN( order, Gen.listOfN( order, g ) ).map(_.toArray)
但是,如果不放入 ClassTag,我无法从中获取 Array[Array[T]]:
def matrix[ T : ClassTag]( g: Gen[ T ] )( order: Int ): Gen[ Array[ Seq[ T ] ] ] =
Gen.listOfN( order, Gen.listOfN( order, g ) ).map(_.toArray)
我有点理解——我在 Scala 方面经验不足。在到达那里的过程中,我尝试了这个:
def matrix2[ T : ClassTag]( g: Gen[ T ] )( order: Int ): Gen[ Array[ Array[ T ] ] ] =
for {
rowSeq <- Gen.listOfN( order, g )
rowArray <- rowSeq.toArray
seqOfRowArrays <- Gen.listOfN( order, rowArray)
matrix <- seqOfRowArrays.toArray
} yield matrix
但编译器抱怨
"type mismatch; found : Array[T] required: org.scalacheck.Gen[Array[Array[T]]]"
在 rowArray 行和
“这条线有多个标记
- 类型不匹配;找到:org.scalacheck.Gen[Array[T]] 要求:scala.collection.GenTraversableOnce[?]"
在 seqOfRowArrays 行。
我的问题是:
1. 有没有更简单的方法来获得定义大小的数组[Array[T]],即一些绑定任意的方法?
2.上面的for expression的输入有什么问题?
3. 当测试失败时,如何让ScalaCheck在收缩过程中不减少顺序?
#1:不用担心 Arbitrary
v. Gen
。他们基本上是一样的。这里有一个很好的答案来解释它们之间的区别:
#2 你正在混合你的 monadic 容器(Gen
和 Array
),而 scala 正在尽最大努力将它们组合起来,这会给你一个令人困惑的错误。
要修复您的类型错误,请执行此操作
def matrix2[ T : ClassTag]( g: Gen[ T ] )( order: Int ): Gen[ Array[ Array[ T ] ] ] =
for {
rowSeq <- Gen.listOfN( order, g )
rowArray = rowSeq.toArray
seqOfRowArrays <- Gen.listOfN( order, rowArray)
} yield seqOfRowArrays.toArray
如果你在终端中运行这个你会发现一些奇怪的东西:
scala> matrix2(Gen.choose(1,10))(3)
res2: org.scalacheck.Gen[Array[Array[Int]]] = org.scalacheck.Gen$$anon@4c93778e
scala> res2.sample
res3: Option[Array[Array[Int]]] = Some([[I@1dd38904)
scala> res3.foreach{a2 => a2.foreach{a => a.foreach{i => println(s" $i")}; println("\n")}}
6
10
5
6
10
5
6
10
5
这只会生成一行,然后在整个矩阵中重复这一行。我对此的解决方案是使用 scalacheck 生成 order^2 元素,然后在事后将它们分组到您的 2D 数组结构中。这是我的 Scala REPL 中的 copy/paste,我在其中执行此操作:
scala> :paste
// Entering paste mode (ctrl-D to finish)
def matrix2[T: ClassTag](g: Gen[T])(order: Int): Gen[Array[Array[T]]] =
Gen.listOfN(order*order, g).map { squareList =>
squareList.toArray.grouped(order).toArray
}
// Exiting paste mode, now interpreting.
matrix2: [T](g: org.scalacheck.Gen[T])(order: Int)(implicit evidence: scala.reflect.ClassTag[T])org.scalacheck.Gen[Array[Array[T]]]
scala> matrix2(Gen.choose(1,10))(3)
res5: org.scalacheck.Gen[Array[Array[Int]]] = org.scalacheck.Gen$$anon@7519bc73
scala> res5.sample.foreach{a2 => a2.foreach{a => a.foreach{i => println(s" $i")}; println("\n")}}
1
9
9
7
6
10
10
2
6
#3 此生成器的 order
不会更改,因为您使用的是固定集合大小的 listOfN
方法。用户指南中的示例仅调整大小,因为它使用了 Gen.sized
生成器。