我正在考虑做类似于安全地复制不同类型的案例类之间的字段但使用重新排序的字段,即
case class A(foo: Int, bar: Int)
case class B(bar: Int, foo: Int)
Run Code Online (Sandbox Code Playgroud)
我想有东西转A(3, 4)成B(4, 3)-不成形LabelledGeneric浮现在脑海,但是
LabelledGeneric[B].from(LabelledGeneric[A].to(A(12, 13)))
Run Code Online (Sandbox Code Playgroud)
结果是
<console>:15: error: type mismatch;
found : shapeless.::[shapeless.record.FieldType[shapeless.tag.@@[Symbol,String("foo")],Int],shapeless.::[shapeless.record.FieldType[shapeless.tag.@@[Symbol,String("bar")],Int],shapeless.HNil]]
(which expands to) shapeless.::[Int with shapeless.record.KeyTag[Symbol with shapeless.tag.Tagged[String("foo")],Int],shapeless.::[Int with shapeless.record.KeyTag[Symbol with shapeless.tag.Tagged[String("bar")],Int],shapeless.HNil]]
required: shapeless.::[shapeless.record.FieldType[shapeless.tag.@@[Symbol,String("bar")],Int],shapeless.::[shapeless.record.FieldType[shapeless.tag.@@[Symbol,String("foo")],Int],shapeless.HNil]]
(which expands to) shapeless.::[Int with shapeless.record.KeyTag[Symbol with shapeless.tag.Tagged[String("bar")],Int],shapeless.::[Int with shapeless.record.KeyTag[Symbol with shapeless.tag.Tagged[String("foo")],Int],shapeless.HNil]]
LabelledGeneric[B].from(LabelledGeneric[A].to(A(12, 13)))
^
Run Code Online (Sandbox Code Playgroud)
如何重新排序记录中的字段(?),这样可以使用最少的样板?
请考虑以下示例:
import shapeless._
case class Foo(bar: String, baz: Boolean)
val labl = LabelledGeneric[Foo]
Run Code Online (Sandbox Code Playgroud)
现在,类型labl是(美化)
LabelledGeneric[Foo] {
type Repr =
FieldType[Symbol @@ String("bar"), String] ::
FieldType[Symbol @@ String("baz"), Boolean] ::
HNil
}
Run Code Online (Sandbox Code Playgroud)
它已经传达了我需要的信息,即案例类字段的名称.
我正在寻找的是一种从labl某种方式走向某种方式的方式
"bar" :: "baz" :: HNil
Run Code Online (Sandbox Code Playgroud)
即将单例类型中包含的信息具体化为值.
这可能吗?我可以使用一个宏,但我觉得我最终会在无形状中重写与该GenericMacros对象非常相似的东西,所以我想知道我是否可以直接利用它.
我想参数化,需要在通用型工作的方法A为其中LabelledGeneric可以检索.这是天真的方法
case class Foo(bar: String, baz: Boolean)
def params[A](a: A) = {
val lbl = LabelledGeneric[A]
val keys = Keys[lbl.Repr].apply
...
}
val myThingy = params(Foo)
Run Code Online (Sandbox Code Playgroud)
当然,潜在的宏抱怨.它不够了解A:
类型A不是类或特征
所以,我试着LabelledGeneric推断
def params[A](a: A)(implicit lbl: LabelledGeneric[A]) = {
val keys = Keys[lbl.Repr].apply
...
}
Run Code Online (Sandbox Code Playgroud)
这似乎有效,但Repr不再知道这种类型HList了
类型参数[lbl.Repr]不符合方法apply的类型参数bounds [L <:shapeless.HList]
好吧,让我们试着更精确
def params[A, Repr <: HList](a: A)(implicit lbl: LabelledGeneric.Aux[A, Repr]) = {
val keys = Keys[lbl.Repr].apply
...
}
Run Code Online (Sandbox Code Playgroud)
现在,Repr绝对是一个HList …
假设我想穿越案例类通用表示描述这里
我已经定义了一些类型类来描述字段:
trait Described[X] extends (X => String)
object Described{
def apply[X](x: X)(implicit desc: Described[X]) = desc(x)
}
Run Code Online (Sandbox Code Playgroud)
定义了一些实例:
implicit object DoubleDescribed extends Described[Double]{
def apply(x: Double) = x.formatted("%01.3f")
}
Run Code Online (Sandbox Code Playgroud)
和一般用户:
import shapeless._
import shapeless.labelled.FieldType
import shapeless.ops.hlist.LeftFolder
object DescrFolder extends Poly2{
implicit def field[X, S <: Symbol](implicit desc: Described[X],
witness: Witness.Aux[S]):
Case.Aux[Seq[String], FieldType[S, X], Seq[String]] =
at[Seq[String], FieldType[S, X]](
(descrs, value) => descrs :+ f"${witness.value.name}: ${desc(value)}")
}
def describe[T <: Product, Repr <: HList](struct: T)
(implicit lgen: LabelledGeneric.Aux[T,Repr],
folder: …Run Code Online (Sandbox Code Playgroud) 我和我的学生都加载了相同的数据集,安装了相同的包,并运行了相同的代码。当我运行“frq”时,我得到一个频率表,并且该变量被标记为“数字”。当我的学生运行相同的代码时,她得到"Error: Can't convert <haven_labelled> to character."
有什么想法我们可能会出错吗?
我知道使用 Shapeless 我可以做这样的事情:
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)
Run Code Online (Sandbox Code Playgroud)
现在我想写一个通用的方法来做到这一点:
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]): …Run Code Online (Sandbox Code Playgroud)