Skip to content

Instantly share code, notes, and snippets.

@notgiorgi
Created December 13, 2017 18:33
Show Gist options
  • Save notgiorgi/ba41db568e6d9f85d2c5d42f0f49c013 to your computer and use it in GitHub Desktop.
Save notgiorgi/ba41db568e6d9f85d2c5d42f0f49c013 to your computer and use it in GitHub Desktop.
trait Generator[T] {
self =>
def generate: T
def map[U](fn: T => U): Generator[U] = new Generator[U]{
def generate = fn(self.generate)
}
def flatMap[U](fn: T => Generator[U]): Generator[U] = fn(self.generate)
}
val integers = new Generator[Int] {
def generate = {
scala.util.Random.nextInt()
}
}
val booleans = integers.map(_ < 0)
def pairs[U, V](u: Generator[U], v: Generator[V]): Generator[(U, V)] =
for {
uval <- u
vval <- v
} yield (uval, vval)
def single[T](t: T) = new Generator[T] {
def generate = t
}
def choose(lo: Int, hi: Int): Generator[Int] =
for (x <- integers) yield lo + x % (hi - lo)
def oneOf[T](xs: T*): Generator[T] = for {
index <- choose(0, xs.length)
} yield xs(index)
def lists: Generator[List[Int]] = for {
isEmpty <- booleans
list <- if (isEmpty) emptyLists else nonEmptyLists
} yield list
def emptyLists = single(Nil)
def nonEmptyLists: Generator[List[Int]] = for {
head <- integers
tail <- lists
} yield head :: tail
lists.generate
trait Tree
case class Fork(left: Tree, right: Tree) extends Tree
case class Leaf(x: Int) extends Tree
def leafs: Generator[Tree] = integers.map(Leaf(_))
def trees: Generator[Tree] = for {
isLeaf <- booleans
tree <- if (isLeaf) leafs else forks
} yield tree
def forks = for {
left <- trees
right <- trees
} yield Fork(left, right)
def test[T](name:String, gen: Generator[T], times: Int)(test: T => Boolean): Unit = {
println(name)
for (i <- 0 until times) {
val value = gen.generate
assert(test(value), s"Test failed for $value")
}
println("All tests pass")
}
test(
"Numbers are odd",
integers.map(x => if (x % 2 != 0) x else x + 1),
50
) (_ % 2 != 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment