1

I am reading and working on the exercises on the book Funcional Programming in Scala. In the chapter about property testing, one exercise ask to implement def listOf[A](g: Gen[A]): SGen[List[A]], here is the relevant code:

case class Gen[+A](sample: State[RNG, A]) {

  def flatMap[B](f: A ⇒ Gen[B]): Gen[B] =
    Gen(sample.flatMap(f(_) sample))

  /* A method alias for the function we wrote earlier. */
  def listOfN(size: Int): Gen[List[A]] =
    Gen.listOfN(size, this)

  def listOfN(size: Gen[Int]): Gen[List[A]] =
    size flatMap (Gen listOfN (_, this))
}

object Gen {
  def listOfN[A](n: Int, g: Gen[A]): Gen[List[A]] =
    Gen(State.sequence(List.fill(n)(g.sample)))

  def listOf[A](g: Gen[A]): SGen[List[A]] =
  //  SGen { n ⇒ g.listOfN(n) }
  //  SGen{listOfN(_, g)}
}

case class SGen[+A](forSize: Int ⇒ Gen[A])

As you can see, listOf[A](g: Gen[A]): SGen[List[A]] is implemented in two ways, the second one is the one I thought, and the first one is the solution provided by the book.

My question is, is there any difference between creating that SGen via the companion object and creating it using the listOfN method on the generator g? I suppose as long as both implementations ends up using g to generate the values, there is little difference.

4

1 回答 1

2

在这个例子中真的没有实际的区别。您可以从Gen.listOfN(size: Int)只是调用伴生对象实现的实现中看到。方法别名的优点之一是您可以在伴随对象中使用更简单的语法,如下所示:

object Gen {
    ...
    def listOf[A](g: Gen[A]): SGen[List[A]] =
        SGen(g.listOfN)
}

当用户制作更大的作品时,拥有这些不同的语法选项可以对清晰度产生更大的影响。

于 2018-12-20T16:25:54.170 回答