Skip to content

Instantly share code, notes, and snippets.

@larsrh
Created July 19, 2019 07:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save larsrh/a7ba75dbc88e3fca60159093996b418b to your computer and use it in GitHub Desktop.
Save larsrh/a7ba75dbc88e3fca60159093996b418b to your computer and use it in GitHub Desktop.
Arbitrary[Arbitrary]
import $ivy.`org.scalacheck::scalacheck:1.14.0`
import org.scalacheck._
import org.scalacheck.Arbitrary._
import scala.reflect._
trait TypeWitness1 {
type F[_]
val name: String
def lift[A](implicit arb: Arbitrary[A]): Arbitrary[F[A]]
override final def toString: String = s"Witness1[$name]"
}
object TypeWitness1 {
val list: TypeWitness1 = new TypeWitness1 {
type F[A] = List[A]
val name = "List"
def lift[A](implicit arb: Arbitrary[A]): Arbitrary[List[A]] = implicitly[Arbitrary[List[A]]]
}
implicit val typeWitness1Arb: Arbitrary[TypeWitness1] = Arbitrary(Gen.oneOf(Seq(list)))
}
trait TypeWitness {
type T
val name: String
implicit val arb: Arbitrary[T]
def forAll(f: T => Prop): Prop = Prop.forAll(f)
def *(that: TypeWitness): TypeWitness = TypeWitness.apply[(this.T, that.T)](s"(${this.name}, ${that.name})")(Arbitrary {
for (x <- this.gen; y <- that.gen) yield (x, y)
})
def +(that: TypeWitness): TypeWitness = TypeWitness.apply[Either[this.T, that.T]](s"Either[${this.name}, ${that.name}]")(Arbitrary {
Gen.oneOf(
this.gen.map((x: this.T) => Left(x): Either[this.T, that.T]),
that.gen.map((y: that.T) => Right(y): Either[this.T, that.T])
)
})
def ^(that: TypeWitness1): TypeWitness = TypeWitness.apply[that.F[this.T]](s"${that.name}[${this.name}]")(that.lift(this.arb))
final def gen: Gen[T] = arb.arbitrary
override final def toString: String = s"Witness[$name]"
}
object TypeWitness {
private def apply[T0 : Arbitrary](name0: String): TypeWitness = new TypeWitness {
type T = T0
val name = name0
val arb = implicitly[Arbitrary[T0]]
}
def ground[T : Arbitrary : ClassTag] = apply[T](classTag[T].toString)
def typeWitnessGen(size: Int): Gen[TypeWitness] = {
val groundGen = Gen.oneOf(ground[Int], ground[String], ground[Float])
lazy val halfSized = typeWitnessGen(size / 2)
lazy val rootSized = typeWitnessGen(Math.sqrt(size).asInstanceOf[Int])
if (size <= 1)
groundGen
else
Gen.frequency(
(5, groundGen),
(2, for (left <- halfSized; right <- halfSized) yield left * right),
(2, for (left <- halfSized; right <- halfSized) yield left + right),
(1, for (base <- rootSized; exp <- arbitrary[TypeWitness1]) yield base ^ exp)
)
}
implicit val typeWitnessArb: Arbitrary[TypeWitness] = Arbitrary(Gen.sized(typeWitnessGen))
}
val witness1 = (TypeWitness.ground[Int] * TypeWitness.ground[String] + TypeWitness.ground[Float]) ^ TypeWitness1.list
println(witness1)
println(witness1.gen.sample)
val witness2 = arbitrary[TypeWitness].sample.get
println(witness2)
println(witness2.gen.sample)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment