One-Minute Example
To run this example, leanprops-core
installation is needed.
import leanprops._
// A small utility function to `inspect` a value in one-line.
def inspect4[A: Inspectable](x: A): String =
Inspectable[A].inspect(x).run(InspectConfig.FourCases)
// ===========================================================================================
//
// Feature 1. Lists all possible values in respect to a type.
// Gets all possible `Int` values.
Listable.list[Int].take(10)
// res0: Stream[Int] = Stream(0, 1, -1, 2, -2, 3, -3, 4, -4, 5)
// Gets all possible `List[Int]` values.
Listable.list[List[Int]].take(10)
// res1: Stream[List[Int]] = Stream(
// List(),
// List(0),
// List(0, 0),
// List(1),
// List(0, 0, 0),
// List(0, 1),
// List(1, 0),
// List(-1),
// List(0, 0, 0, 0),
// List(0, 0, 1)
// )
// Gets all possible `(Int, Int) => Int` values.
Listable.list[(Int, Int) => Int].take(10).map(inspect4[(Int, Int) => Int])
// res2: Stream[String] = Stream(
// "(_ => 0)",
// "((x, y) => (x, y) match { case (0, 0) => 1; case _ => 0 })",
// "(_ => 1)",
// "((x, y) => (x, y) match { case (0, 0) => -1; case _ => 0 })",
// "((x, y) => (x, y) match { case (0, 1) => 1; case _ => 0 })",
// "((x, y) => (x, y) match { case (1, 0) => 1; case _ => 0 })",
// "((x, y) => (x, y) match { case (0, 0) => 0; case _ => 1 })",
// "((x, y) => (x, y) match { case (0, 0) => 2; case _ => 0 })",
// "((x, y) => (x, y) match { case (0, 1) => -1; case _ => 0 })",
// "((x, y) => (x, y) match { case (1, 0) => -1; case _ => 0 })"
// )
// ===========================================================================================
//
// Feature 2. `inspect` - better `toString`.
// Inspects an infinite `Stream[Int]`
println(inspect(Stream.from(1)))
// Stream(1, 2, 3, 4, 5, 6, 7, 8, ...)
// Inspects `&&` function.
println(inspect { (x: Boolean, y: Boolean) => x && y })
// ((x, y) => (x, y) match {
// case (true, true) => true
// case _ => false
// })
// Inspects `_.head` function.
println(inspect { (xs: List[Int]) => xs.head })
// (x => x match {
// case List() => throw new NoSuchElementException("head of empty list")
// case List(0) => 0
// case List(0, 0) => 0
// case List(1) => 1
// case List(0, 0, 0) => 0
// case List(0, 1) => 0
// case List(1, 0) => 1
// case List(-1) => -1
// ...
// })
// ===========================================================================================
//
// Feature 3. Tests a property.
// Checks `x * 0 == 0` against first 100-elements of the above list.
holds(100) { (x: Int) => x * 0 == 0 }
// res6: Boolean = true
// Above is the same as:
Listable.list[Int].take(100).forall { x => x * 0 == 0 }
// res7: Boolean = true
// Finds an example that makes a difference between `foldLeft` and `foldRight`.
counterExample(1000) { (xs: List[Int], x: Int, f: (Int, Int) => Int) =>
xs.foldLeft(x)(f) == xs.foldRight(x)(f)
}
// res8: Option[Seq[Seq[String]]] = Some(
// List(
// List(
// "List(0)",
// "1",
// "((x, y) => (x, y) match { case (0, 1) => 1; case _ => 0 })"
// )
// )
// )