All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scalaprops.ScalapropsShapeless.scala Maven / Gradle / Ivy

package scalaprops

import shapeless3.deriving.K0
import scala.deriving.Mirror

sealed abstract class ScalapropsShapelessInstances {

  final def cogenFromPolyFunction[A](f: [t] => (a: A, s: CogenState[t]) => CogenState[t]): Cogen[A] =
    new Cogen[A] {
      override def cogen[B](a: A, s: CogenState[B]) = f[B](a, s)
    }

  inline implicit def cogenCoproduct[A](using inst: => K0.CoproductInstances[Cogen, A]): Cogen[A] =
    cogenFromPolyFunction[A](
      [B] => (a: A, s: CogenState[B]) => inst.fold(a)([t <: A] => (c: Cogen[t], t: t) => c.cogen(t, s))
    )

  inline implicit def cogenProduct[A](using inst: => K0.ProductInstances[Cogen, A]): Cogen[A] =
    cogenFromPolyFunction[A](
      [B] =>
        (a: A, s: CogenState[B]) =>
          inst.foldLeft[CogenState[B]](a)(s)(
            [t] => (acc: CogenState[B], c: Cogen[t], t: t) => c.cogen(t, acc)
        )
    )

  inline implicit def genProduct[A](using inst: => K0.ProductInstances[Gen, A]): Gen[A] =
    Gen.gen[A] { (size, rand) =>
      val (x, y) = inst.unfold[Rand](rand) {
        [t] =>
          (r: Rand, g: Gen[t]) => {
            val (next, a) = g.f(size, r)
            (next, Option(a))
        }
      }
      (x, y.get)
    }

  inline implicit def genCoproduct[A](using inst: => K0.CoproductInstances[Gen, A], mirror: Mirror.SumOf[A]): Gen[A] =
    Gen.gen[A] { (size, r1) =>
      val (r2, i) = r1.nextInt
      val index = if (i == Int.MinValue) {
        0
      } else {
        i.abs % valueOf[Tuple.Size[mirror.MirroredElemTypes]]
      }
      inst.inject[(Rand, A)](index) {
        [t <: A] => (g: Gen[t]) => g.f(size, r2)
      }
    }

}

object ScalapropsShapeless extends ScalapropsShapelessInstances {

  inline implicit def deriveGen[A](using gen: K0.Generic[A]): Gen[A] =
    gen.derive(genProduct, genCoproduct)

  inline implicit def deriveCogen[A](using gen: K0.Generic[A]): Cogen[A] =
    gen.derive(cogenProduct, cogenCoproduct)

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy