我知道用無形的,我可以做這樣的事情:一般地變身一類到另一個使用無形+ LabelledGenerics
import shapeless._, syntax.singleton._, record._
case class Foo(x: Int, y: String)
case class RichFoo(x: Int, y: String, z: Double)
def makeRich(foo: Foo): RichFoo = {
val x = ('z ->> 0.9)
val repr = LabelledGeneric[Foo].to(foo) + x
LabelledGeneric[RichFoo].from(repr)
}
val a = Foo(1, "hello")
val b = makeRich(a)
現在我想編寫一個通用的方法來做到這一點:
trait Morph[A, B, AR, BR] {
def apply(a: A)(f: AR => BR): B
}
object Morph {
implicit def genericMorph[A, B, AR, BR](implicit genA: LabelledGeneric.Aux[A, AR], genB: LabelledGeneric.Aux[B, BR]): Morph[A, B, AR, BR] =
new Morph[A, B, AR, BR] {
override def apply(a: A)(f: AR => BR) = genB.from(f(genA.to(a)))
}
implicit class Syntax[A](a: A) {
def morph[AR, BR, B](f: AR => BR)(implicit morph: Morph[A, B, AR, BR]): B =
morph(a)(f)
}
}
但是,現在這個用法是不可靠的?
val a = Foo(1, "hello")
a.morph[???, ???, RichFoo](_ + ('z ->> 0.9))
什麼是設計此API的更好方法?
我想是這樣的:
implicit class Syntax[A](a: A) {
def morphTo[B] = new {
def using[AR <: HList, BR <: HList](f: AR => BR)(implicit morph: Morph[A, B, AR, BR]): B =
morph(a)(f)
}
}
a.morphTo[RichFoo].using(_ :+ ('z ->> 0.9))
但它並沒有真正的工作
哈不錯的把戲減少一個隱式搜索! – pathikrit