代码之家  ›  专栏  ›  技术社区  ›  E Bro

标量检查集大小数组生成器

  •  0
  • E Bro  · 技术社区  · 10 年前

    我正在尝试制作一个ScalaCheck矩阵生成器,它将生成指定顺序(大小/尺寸)的2D阵列/矩阵。我从教程中的示例开始,并将其简化为(对于原型设计——我理解我应该使用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
    

    但编译器抱怨
    “类型不匹配;找到:需要Array[T]:org.scalach.Gen[Array[Array[T]]]”
    在rowArray行和
    “此行有多个标记 -类型不匹配;找到:org.scalacheck。需要Gen[Array[T]]:scala.collection.GenTraversableOnce[?]"
    在seqOfRowArrays行。

    我的问题是:
    1.是否有一种更简单的方法来获得定义大小的Array[Array[T]],即绑定任意的方法?
    2.键入上面的表达式有什么问题?
    3.当测试失败时,如何防止ScalaCheck在收缩过程中减少订单?

    1 回复  |  直到 10 年前
        1
  •  0
  •   Community Mohan Dere    8 年前

    #1: 别担心 Arbitrary v Gen 。它们基本相同。这里有一个很好的答案来解释它们之间的区别: Why do you need Arbitraries in scalacheck?

    #2你正在混合你的monadic容器( 消息 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$6@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
    

    这只生成一行,然后在整个矩阵中重复同一行。对此,我的解决方案是使用scalacleck生成^2个元素,然后将它们分组到2D数组结构中。这里是我的Scala REPL的复制/粘贴:

    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$1: 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$6@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 发电机