Generation of arbitrary case classes / ADTs with scalacheck and shapeless
alexarchambault on scala-cli
Switch build to Scala CLI Use Scala CLI nightly (compare)
alexarchambault on master
Update sbt to 1.6.2 (#246) * A… (compare)
alexarchambault on scala-cli
Use Scala CLI nightly (compare)
alexarchambault on sbt-main-line
Use sbt main line launcher on CI (compare)
alexarchambault on scala-cli
Switch build to Scala CLI (compare)
alexarchambault on scala-cli
Switch build to Scala CLI (compare)
alexarchambault on sbt-main-line
alexarchambault on master
Use sbt main line launcher on C… (compare)
alexarchambault on sbt-main-line
Use sbt main line launcher on CI (compare)
alexarchambault on scala-cli
Switch build to Scala CLI (compare)
LabelledGeneric
Hello. I am getting compiler "stackoverflow" when trying to derive generators for scalapb data.
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$typedImplicit(Implicits.scala:622)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.rankImplicits(Implicits.scala:1213)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.findBest(Implicits.scala:1248)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:1305)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1730)
at scala.tools.nsc.typechecker.Implicits.inferImplicit1(Implicits.scala:112)
at scala.tools.nsc.typechecker.Implicits.inferImplicit(Implicits.scala:91)
at scala.tools.nsc.typechecker.Implicits.inferImplicit$(Implicits.scala:88)
at scala.tools.nsc.Global$$anon$5.inferImplicit(Global.scala:483)
at scala.tools.nsc.typechecker.Implicits.$anonfun$inferImplicit$1(Implicits.scala:144)
at scala.tools.nsc.typechecker.Implicits.inferImplicit(Implicits.scala:144)
at scala.tools.nsc.typechecker.Implicits.inferImplicit$(Implicits.scala:142)
at scala.tools.nsc.Global$$anon$5.inferImplicit(Global.scala:483)
at scala.reflect.macros.contexts.Typers.inferImplicitValue(Typers.scala:56)
at scala.reflect.macros.contexts.Typers.inferImplicitValue$(Typers.scala:54)
at scala.reflect.macros.contexts.Context.inferImplicitValue(Context.scala:18)
at scala.reflect.macros.contexts.Context.inferImplicitValue(Context.scala:18)
at shapeless.LazyMacros$DerivationContext$State$.resolveInstance(lazy.scala:303)
at shapeless.LazyMacros$DerivationContext.resolve0(lazy.scala:421)
at shapeless.LazyMacros$DerivationContext.$anonfun$deriveLowPriority$1(lazy.scala:449)
at scala.Option.flatMap(Option.scala:283)
at shapeless.LazyMacros$DerivationContext.helper$2(lazy.scala:446)
at shapeless.LazyMacros$DerivationContext.deriveLowPriority(lazy.scala:483)
at shapeless.LazyMacros$DerivationContext.derive(lazy.scala:494)
at shapeless.LazyMacros$DerivationContext$State$.deriveInstance(lazy.scala:327)
at shapeless.LazyMacrosCompat.deriveInstance(lazymacros.scala:50)
at shapeless.LazyMacrosCompat.deriveInstance$(lazymacros.scala:33)
at shapeless.LazyMacros$.deriveInstance(lazy.scala:573)
at shapeless.LazyMacros.mkImpl(lazy.scala:216)
at shapeless.LazyMacros.mkStrictImpl(lazy.scala:209)
at shapeless.LazyMacrosRef.mkStrictImpl(lazyref.scala:39)
at scala.reflect.macros.runtime.JavaReflectionRuntimes$JavaReflectionResolvers.$anonfun$resolveJavaReflectionRuntime$5(JavaReflectionRuntimes.scala:45)
Can I do something with this or I have big nested type that can not be derived?
-Xss2m
Hi,. In the following example, is there a way to create one instance of each subtype predictably, I want to remove randomness and create one instance for each subtype in ADT's?
import org.scalacheck.ScalacheckShapeless._
sealed trait Base
case class BaseIntString(i: Int, s: String) extends Base
case class BaseDoubleBoolean(d: Double, b: Boolean) extends Base
val arb = implicitly[Arbitrary[Base]]
println(arb.sample)
println(arb.sample)
println(arb.sample)
here arb.sample
gives random instance for one of the subtype
/**
* Case class representing a canonical Snowplow event.
*
* @see https://github.com/snowplow/snowplow/wiki/canonical-event-model
*/
case class Event(app_id: Option[String],
platform: Option[String],
etl_tstamp: Option[Instant],
collector_tstamp: Instant,
dvce_created_tstamp: Option[Instant],
event: Option[String],
event_id: UUID,
txn_id: Option[Int],
name_tracker: Option[String],
v_tracker: Option[String],
v_collector: String,
v_etl: String,
user_id: Option[String],
user_ipaddress: Option[String],
user_fingerprint: Option[String],
domain_userid: Option[String],
domain_sessionidx: Option[Int],
network_userid: Option[String],
geo_country: Option[String],
geo_region: Option[String],
geo_city: Option[String],
geo_zipcode: Option[String],
geo_latitude: Option[Double],
geo_longitude: Option[Double],
geo_region_name: Option[String],
ip_isp: Option[String],
ip_organization: Option[String],
ip_domain: Option[String],
ip_netspeed: Option[String],
page_url: Option[String],
page_title: Option[String],
page_referrer: Option[String],
page_urlscheme: Option[String],
page_urlhost: Option[String],
page_urlport: Option[Int],
page_urlpath: Option[String],
page_urlquery: Option[String],
page_urlfragment: Option[String],
refr_urlscheme: Option[String],
refr_urlhost: Option[String],
refr_urlport: Option[Int],
refr_urlpath: Option[String],
refr_urlquery: Option[String],
refr_urlfragment: Option[String],
refr_medium: Option[String],
refr_source: Option[String],
refr_term: Option[String],
mkt_medium: Option[String],
mkt_source: Option[String],
mkt_term: Option[String],
mkt_content: Option[String],
mkt_campaign: Option[String],
contexts: Contexts,
se_category: Option[String],
se_action: Option[String],
se_label: Option[String],
se_property: Option[String],
se_value: Option[Double],
unstruct_event: UnstructEvent,
tr_orderid: Option[String],
tr_affiliation: Option[String],
tr_total: Option[Double],
tr_tax: Option[Double],
tr_shipping: Option[Double],
tr_city: Option[String],
tr_state: Option[String],
tr_country: Option[String],
....
I'm facing the same issue as @hejfelix, while using implicitly[Arbitrary[BigCaseClass]].arbitrary:
Could not write class xxx because it exceeds JVM code size limits. Method inst$macro$135$lzycompute's code too large!
The case class has 130 fields.
Any workaround to solve this issue? Thanks!
I found a workaround using generics and implicit generators:
// primitive generators
implicit def stringGen(implicit arbString: Arbitrary[String]): Gen[String] = arbString.arbitrary
implicit def intGen(implicit arbInt: Arbitrary[Int]): Gen[Int] = arbInt.arbitrary
// hlist generator
implicit def hnilGen: Gen[HNil] = Gen.const(HNil)
implicit def hlistGen[H, T <: HList](implicit headGen: Gen[H], tailGen: Gen[T]) = headGen.flatMap(head => tailGen.map(tail => head :: tail))
// case class generator
implicit def caseClassGen[T, L <: HList](implicit generic: Generic.Aux[T, L], lGen: Gen[L]): Gen[T] = lGen.map(generic.from)
def generator[A](implicit gen: Gen[A]): Gen[A] = gen
Then you can generate arbitrary big case classes like this:
implicit val generic = Generic[YourBigCaseClass]
val gen = generator[YourBigCaseClass]
val sample = Gen.nonEmptyListOf(gen).sample.get
I hope that helps anyone facing this limitation.
ShrinkLowPriority
trait but it seems to conflict with the internals of scalacheck-shapeless. I get Error:(27, 88) ambiguous implicit values:
both method derivedShrink in trait DerivedInstances of type [T](implicit ev: shapeless.LowPriority.Ignoring[String("shrinkAny")], implicit underlying: shapeless.Strict[org.scalacheck.derive.MkShrink[T]])org.scalacheck.Shrink[T]
and method shrinkAny in trait ShrinkLowPriority of type [T]=> org.scalacheck.Shrink[T]
match expected type ...
Looking at the source there is a
implicit def derivedShrink[T]
(implicit
ev: LowPriority.Ignoring[Witness.`"shrinkAny"`.T],
underlying: Strict[MkShrink[T]]
): Shrink[T] =
underlying.value.shrink
But I don't understand what it does.
Hello, can scalacheck-shapeless work with case classes with in turn have fields like Instant / Date / Curency / scala enumeratum, if there are "manual" arbitraries provided for these ?
I can't seem to make it work
the closest i get is to a
scala.UninitializedFieldError: Uninitialized field
edit: it works just have to have all the implicit imports near
import org.scalacheck.ScalacheckShapeless._
Hi all,
I'm using "com.github.alexarchambault" %% "scalacheck-shapeless_1.14" % "1.2.5", scala 2.13.5.
I expect implicitly[Arbitrary[IntWr]]
to use arb
in the code below, but it doesn't.
case class IntWr(int: Int)
val intGen = Gen.choose(5, 9)
def shapelessCustom = {
import org.scalacheck.ScalacheckShapeless._
implicit val arb: Arbitrary[Int] = Arbitrary(intGen)
mkList(implicitly[Arbitrary[IntWr]])
}
private def mkList[T](gen: Arbitrary[T]): List[T] =
List.fill(10)(gen.arbitrary.sample.get)
For instance, here the correct Arbitrary[Int] is used:
def custom: List[Int] = {
implicit val arb: Arbitrary[Int] = Arbitrary(intGen)
mkList(implicitly[Arbitrary[Int]])
}
Is this behavior expected?
How can I use custom arbitrary for a case class attribute?
❯ scala -Wmacros:help
Usage: -Wmacros:<mode> where <mode> choices are none, before, after, both (default: before).
none Do not inspect expansions or their original trees when generating unused symbol warnings.
before Only inspect unexpanded user-written code for unused symbols.
after Only inspect expanded trees when generating unused symbol warnings.
both Inspect both user-written code and expanded trees when generating unused symbol warnings.
Wow, I didn't know that compiler flags show some help this way. Neither I knew about flag❯ scala -Wmacros:help Usage: -Wmacros:<mode> where <mode> choices are none, before, after, both (default: before).
-Wmacros
:)).Well ... it works on my machine :smile: https://scastie.scala-lang.org/7Ji2AhrCT5GK2FGyJ3yG8A
hmmmmm