Skip to content

Instantly share code, notes, and snippets.

@rsuniev
Created June 12, 2015 08:07
Show Gist options
  • Save rsuniev/823bd09c2645a8914e26 to your computer and use it in GitHub Desktop.
Save rsuniev/823bd09c2645a8914e26 to your computer and use it in GitHub Desktop.
package derivation
import shapeless._
import shapeless.ops.coproduct.Length
import shapeless.ops.nat.ToInt
import scala.util.Random
sealed trait Animal
case class Cat(name: String, fish: Int) extends Animal
case class Dog(name: String, bones: Int) extends Animal
case class Cow(name: String) extends Animal
object Arbitrary {
def apply[T](implicit a: Arbitrary[T]) = a
implicit val arbitraryHNil: Arbitrary[HNil] = new Arbitrary[HNil] {
def value = HNil
}
implicit def arbitraryHCon[H, T <: HList](
implicit h: Arbitrary[H], t: Arbitrary[T]): Arbitrary[H :: T] = new Arbitrary[H :: T] {
def value = h.value :: t.value
}
implicit val arbitraryCNil: Arbitrary[CNil] = new Arbitrary[CNil] {
def value = ???
}
implicit def arbitraryCCon[H, T <: Coproduct, N <: Nat](
implicit h: Arbitrary[H],
t: Arbitrary[T],
l: Length.Aux[T, N],
n: ToInt[N]): Arbitrary[H :+: T] = new Arbitrary[H :+: T] {
def value = {
val choice = Random.nextInt(1 + n())
if(choice == 0) Inl(h.value) else Inr(t.value)
}
}
/*implicit def arbitaryCLast[H](implicit h: Arbitrary[H]): Arbitrary[H :+: CNil] = new Arbitrary[H :+: CNil] {
def value = Inl(h.value)
}*/
implicit val arbitraryInt: Arbitrary[Int] = new Arbitrary[Int] {
def value = Random.nextInt(10)
}
implicit val arbitraryString: Arbitrary[String] = new Arbitrary[String] {
def value = s"<<${Random.nextInt(10)}>>"
}
implicit def arbitraryGen[T, R](implicit
gen: Generic.Aux[T, R],
arbitraryRepr: Arbitrary[R]): Arbitrary[T] = new Arbitrary[T] {
def value: T = gen.from(arbitraryRepr.value)
}
}
trait Arbitrary[T] {
def value: T
}
object Demo extends App {
for(i <- 1 to 10) println(Arbitrary[Animal].value)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment