tag studio programacion optimizar móviles lentas etiquetas desarrollo curso consultas aplicaciones scala shapeless labelled-generic

scala - studio - Sin forma: convierta una clase de caso en otra con campos en orden diferente



optimizar consultas lentas mysql (2)

Estoy pensando en hacer algo similar a copiar de forma segura campos entre clases de casos de diferentes tipos pero con campos reordenados, es decir

case class A(foo: Int, bar: Int) case class B(bar: Int, foo: Int)

Y me gustaría tener algo para convertir una A(3, 4) en una B(4, 3) ; sin LabelledGeneric '' LabelledGeneric sin LabelledGeneric viene a mi mente

LabelledGeneric[B].from(LabelledGeneric[A].to(A(12, 13)))

resultados en

<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))) ^

¿Cómo puedo reordenar los campos en el registro (?) Para que esto pueda funcionar con un mínimo de repetitivo?


Como se notó en @MilesSabin (creador sin forma divina), hay una operación de alineación, se usa como:

import ops.hlist.Align val aGen = LabelledGeneric[A] val bGen = LabelledGeneric[B] val align = Align[aGen.Repr, bGen.Repr] bGen.from(align(aGen.to(A(12, 13)))) //> res0: B = B(13,12)

PS notó que hay un ejemplo en GitHub .


Debería dejar esto para Miles, pero es hora feliz de donde soy y no puedo resistirme. Como señala en un comentario anterior, la clave es ops.hlist.Align , que funcionará bien para los registros (que después de todo son listas especiales).

Si desea una buena sintaxis, debe usar un truco como el siguiente para separar la lista de parámetros de tipo con el objetivo (que desea proporcionar explícitamente) de la lista de parámetros de tipo con todas las otras cosas (que desea inferir) ):

import shapeless._, ops.hlist.Align class SameFieldsConverter[T] { def apply[S, SR <: HList, TR <: HList](s: S)(implicit genS: LabelledGeneric.Aux[S, SR], genT: LabelledGeneric.Aux[T, TR], align: Align[SR, TR] ) = genT.from(align(genS.to(s))) } def convertTo[T] = new SameFieldsConverter[T]

Y entonces:

case class A(foo: Int, bar: Int) case class B(bar: Int, foo: Int)

Y entonces:

scala> convertTo[B](A(12, 13)) res0: B = B(13,12)

Tenga en cuenta que encontrar instancias de alineación será costoso en tiempo de compilación para clases de casos grandes.