我正在嘗試使用無形生成案例類的實體
這適用于生成實體Foo
case class Foo(x: Int, y: String)
class Context {
val random = new Random()
}
def genInt(context: Context): Int = {
context.random.nextInt()
}
def genString(context: Context): String = {
context.random.nextString(16)
}
object ClassesToGenerators extends Poly1 {
implicit def caseInt = at[Class[Int]](_ => genInt(_))
implicit def caseString = at[Class[String]](_ => genString(_))
}
val gen = Generic[Foo]
val context = new Context()
val classes = classOf[Int] :: classOf[String] :: HNil // can't figure out how to get this hlist programmatically
val generators = classes.map(ClassesToGenerators)
gen.from(generators.zipApply(generators.mapConst(context)))
但是,我的目標是寫一些可重用的東西,比如
def newInstance[T] -> T:
???
它可以生成僅采用 int 和 string 引數的任何案例類的實體。
如代碼片段中所述,我一直在獲取案例類屬性型別的 hlist,即希望轉換case class Foo(x: Int, y: String)為classOf[Int] :: classOf[String] :: HNil. 對此問題的任何其他方法也非常感謝,但我不是在尋找生成案例類隨機實體的通用方法(因為我的用例不同,并且僅使用隨機生成器作為示例)
uj5u.com熱心網友回復:
恕我直言,當您忘記所有花哨的東西而只關注簡單的型別類派生時,最好使用ShapelessHList ,如下所示:
import shapeless.{Generic, HList, HNil, :: => :!:}
import scala.util.Random
trait Context {
def random: Random
}
object Context {
object implicits {
implicit final val global: Context = new Context {
override final val random: Random = new Random()
}
}
}
trait Generator[A] {
def generate(context: Context): A
}
object Generator {
final def apply[A](implicit ev: Generator[A]): ev.type = ev
final def generate[A](implicit ev: Generator[A], ctx: Context): A =
ev.generate(ctx)
implicit final val IntGenerator: Generator[Int] =
new Generator[Int] {
override def generate(context: Context): Int =
context.random.nextInt()
}
implicit final val StringGenerator: Generator[String] =
new Generator[String] {
override def generate(context: Context): String =
context.random.nextString(16)
}
implicit final def auto[P <: Product](implicit ev: GeneratorGen[P]): Generator[P] = ev
}
sealed trait GeneratorRepr[R <: HList] extends Generator[R]
object GeneratorRepr {
implicit final val HNilGeneratorRepr: GeneratorRepr[HNil] =
new GeneratorRepr[HNil] {
override def generate(context: Context): HNil =
HNil
}
implicit final def HConsGeneratorRepr[E, T <: HList](
implicit ev: Generator[E], tail: GeneratorRepr[T]
): GeneratorRepr[E :!: T] =
new GeneratorRepr[E :!: T] {
override def generate(context: Context): E :!: T =
ev.generate(context) :: tail.generate(context)
}
}
sealed trait GeneratorGen[P <: Product] extends Generator[P]
object GeneratorGen {
implicit final def instance[P <: Product, R <: HList](
implicit gen: Generic.Aux[P, R], ev: GeneratorRepr[R]
): GeneratorGen[P] = new GeneratorGen[P] {
override def generate(context: Context): P =
gen.from(ev.generate(context))
}
}
可以這樣使用:
import Context.implicits.global
final case class Foo(x: Int, y: String)
val result = Generator.generate[Foo]
// result: Foo = Foo(-2127375055, "鞰???沺???????闉?雦峷")
您可以看到這里運行的代碼。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/474439.html
上一篇:我可以使用型別類來獲得子類的非混合、組合的共享實作以及回傳子型別別嗎?
下一篇:Scala獲取java.lang.ClassCastException:java.math.BigDecimal無法轉換為java.lang.Double
