过滤掉案例类中的字段

时间:2016-07-20 22:53:42

标签: scala shapeless

我试图过滤掉可能位于层次结构中的案例类中的特定字段:

import shapeless._
object removeField {

  import labelled._
  import ops.record._

  trait RemoveField[T] {
    def removeField(t: T, field:Witness): HList
  }

  object RemoveField {

    implicit def generic[F, G](implicit gen: LabelledGeneric.Aux[F, G], sg: Lazy[RemoveField[G]]): RemoveField[F] =
      new RemoveField[F] {
        def removeField(f: F, field:Witness) = sg.value.removeField(gen.to(f), field)
      }

    implicit def product: RemoveField[HNil] =
      new RemoveField[HNil] {
        def removeField(p: HNil, field:Witness): HList = HNil
      }

    implicit def product[K <: Symbol, V, T <: HList]
      (implicit
        key: Witness.Aux[K],
        selector: Selector.Aux[FieldType[K, V] :: T, K, Symbol],
        sv: Lazy[RemoveField[V]],
        st: Lazy[RemoveField[T]]
      ): RemoveField[FieldType[K, V] :: T] =
        new RemoveField[FieldType[K, V] :: T] {
          def removeField(p: FieldType[K, V] :: T, field:Witness): HList = {
            if (selector(p) == selector(p)) sv.value.removeField(p.head, field)
            else p.head :: st.value.removeField(p.tail, field)
          }
        }

    implicit def cnil: RemoveField[CNil] =
      new RemoveField[CNil] {
        def removeField(p: CNil, field:Witness) = HNil
      }

    implicit def coproduct[K <: Symbol, V, T <: Coproduct]
      (implicit
        key: Witness.Aux[K],
        sv: Lazy[RemoveField[V]],
        st: Lazy[RemoveField[T]]
      ): RemoveField[FieldType[K, V] :+: T] =
        new RemoveField[FieldType[K, V] :+: T] {
          def removeField(c: FieldType[K, V] :+: T, field:Witness): HList =
            c match {
              case Inl( head ) => sv.value.removeField(head, field )
              case Inr( tail ) => st.value.removeField(tail, field )
            }
        }
  }

  implicit class RemoveFieldOps[T](x: T)(implicit removeFieldT: RemoveField[T]) {
    def removeField(field:Witness): HList = removeFieldT.removeField(x, field)
  }

  sealed trait Animal
  case class Cat(name: String, fish: Int) extends Animal
  case class Dog(name: String, bones: Int) extends Animal

  val felix:Cat = Cat("Felix", 1)
  val tigger = Dog("Tigger", 2)
}

所以当我这样做时:

scala> import removeField._
import removeField._

scala> felix
res0: removeField.Cat = Cat(Felix,1)

scala> felix.removeField('name)

它没有编译,我认为问题是RemoveField[G]无法找到,下面是隐式解决方案的完整痕迹,但我认为这应该是有效的

 <console>:15: removeField.this.RemoveField.<product: error> is not a valid implicit value for removeField.RemoveField[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]]] because:
type mismatch;
 found   : [K <: Symbol, V, T <: shapeless.HList](implicit key: shapeless.Witness.Aux[K], implicit selector: shapeless.ops.record.Selector.Aux[shapeless.::[shapeless.labelled.FieldType[K,V],T],K,Symbol], implicit sv: shapeless.Lazy[removeField.RemoveField[V]], implicit st: shapeless.Lazy[removeField.RemoveField[T]])removeField.RemoveField[shapeless.::[shapeless.labelled.FieldType[K,V],T]] <and> => removeField.RemoveField[sh...<console>:15: shapeless.this.Generic.materialize is not a valid implicit value for shapeless.Generic.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],V] because:
hasMatchingSymbol reported error: No Generic instance available for HList or Coproduct
       felix.removeField('name)
       ^

因为我理解LabelledGeneric会&#34;返回&#34; V with KeyTag[K, V] :: T又称FieldType[K, V]类型的东西 其中K <: SymbolT <: HList

似乎这样做,类型是

Generic.Aux[
 String with KeyTag[Symbol with Tagged[String("name"),String]] :: 
Int with KeyTag[Symbol with Tagged[String("fish")],Int] :: 
shapeless.HNil],
 V
]

那么为什么我的类型类的product实例&#34;选择&#34;那个? 完整的痕迹:

  <console>:15: shapeless.this.Generic.materialize is not a valid implicit value for shapeless.Generic.Aux[removeField.Cat,V] because:
type parameters weren't correctly instantiated outside of the implicit tree: inferred type arguments [shapeless.::[String,shapeless.::[Int,shapeless.HNil]],Nothing] do not conform to method materializeCoproduct's type parameter bounds [V <: shapeless.Coproduct,R <: shapeless.Coproduct]
       felix.removeField('name)
       ^
<console>:15: shapeless.this.LabelledGeneric.materializeCoproduct is not a valid implicit value for shapeless.LabelledGeneric.Aux[removeField.Cat,G] because:
hasMatchingSymbol reported error: could not find implicit value for parameter gen: shapeless.Generic.Aux[removeField.Cat,V]
       felix.removeField('name)
       ^
<console>:15: removeField.this.RemoveField.<product: error> is not a valid implicit value for removeField.RemoveField[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]]] because:
type mismatch;
 found   : [K <: Symbol, V, T <: shapeless.HList](implicit key: shapeless.Witness.Aux[K], implicit selector: shapeless.ops.record.Selector.Aux[shapeless.::[shapeless.labelled.FieldType[K,V],T],K,Symbol], implicit sv: shapeless.Lazy[removeField.RemoveField[V]], implicit st: shapeless.Lazy[removeField.RemoveField[T]])removeField.RemoveField[shapeless.::[shapeless.labelled.FieldType[K,V],T]] <and> => removeField.RemoveField[sh...<console>:15: shapeless.this.Generic.materialize is not a valid implicit value for shapeless.Generic.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],V] because:
hasMatchingSymbol reported error: No Generic instance available for HList or Coproduct
       felix.removeField('name)
       ^
<console>:15: shapeless.this.LabelledGeneric.materializeCoproduct is not a valid implicit value for shapeless.LabelledGeneric.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],G] because:
hasMatchingSymbol reported error: could not find implicit value for parameter gen: shapeless.Generic.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],V]
       felix.removeField('name)
       ^
<console>:15: shapeless.this.Generic.materialize is not a valid implicit value for shapeless.Generic.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],V] because:
hasMatchingSymbol reported error: No Generic instance available for HList or Coproduct
       felix.removeField('name)
       ^
<console>:15: shapeless.this.LabelledGeneric.materializeProduct is not a valid implicit value for shapeless.LabelledGeneric.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],G] because:
hasMatchingSymbol reported error: could not find implicit value for parameter gen: shapeless.Generic.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],V]
       felix.removeField('name)
       ^
<console>:15: removeField.this.RemoveField.generic is not a valid implicit value for removeField.RemoveField[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]]] because:
hasMatchingSymbol reported error: could not find implicit value for parameter gen: shapeless.LabelledGeneric.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],G]
       felix.removeField('name)
       ^
<console>:15: shapeless.this.Lazy.mkLazy is not a valid implicit value for shapeless.Lazy[removeField.RemoveField[this.Out]] because:
hasMatchingSymbol reported error: Unable to derive removeField.RemoveField[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]]]
       felix.removeField('name)
       ^
<console>:15: removeField.this.RemoveField.generic is not a valid implicit value for removeField.RemoveField[removeField.Cat] because:
hasMatchingSymbol reported error: could not find Lazy implicit value of type removeField.RemoveField[G]
       felix.removeField('name)
       ^
<console>:15: RemoveFieldOps is not a valid implicit value for removeField.felix.type => ?{def removeField: ?} because:
could not find implicit value for parameter removeFieldT: removeField.RemoveField[removeField.Cat]
       felix.removeField('name)
       ^
<console>:15: shapeless.this.Generic.materialize is not a valid implicit value for shapeless.Generic.Aux[removeField.Cat,V] because:
type parameters weren't correctly instantiated outside of the implicit tree: inferred type arguments [shapeless.::[String,shapeless.::[Int,shapeless.HNil]],Nothing] do not conform to method materializeCoproduct's type parameter bounds [V <: shapeless.Coproduct,R <: shapeless.Coproduct]
       felix.removeField('name)
       ^
<console>:15: shapeless.this.LabelledGeneric.materializeCoproduct is not a valid implicit value for shapeless.LabelledGeneric.Aux[removeField.Cat,G] because:
hasMatchingSymbol reported error: could not find implicit value for parameter gen: shapeless.Generic.Aux[removeField.Cat,V]
       felix.removeField('name)
       ^
<console>:15: removeField.this.RemoveField.<product: error> is not a valid implicit value for removeField.RemoveField[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]]] because:
type mismatch;
 found   : [K <: Symbol, V, T <: shapeless.HList](implicit key: shapeless.Witness.Aux[K], implicit selector: shapeless.ops.record.Selector.Aux[shapeless.::[shapeless.labelled.FieldType[K,V],T],K,Symbol], implicit sv: shapeless.Lazy[removeField.RemoveField[V]], implicit st: shapeless.Lazy[removeField.RemoveField[T]])removeField.RemoveField[shapeless.::[shapeless.labelled.FieldType[K,V],T]] <and> => removeField.RemoveField[sh...<console>:15: shapeless.this.Generic.materialize is not a valid implicit value for shapeless.Generic.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],V] because:
hasMatchingSymbol reported error: No Generic instance available for HList or Coproduct
       felix.removeField('name)
       ^
<console>:15: shapeless.this.LabelledGeneric.materializeCoproduct is not a valid implicit value for shapeless.LabelledGeneric.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],G] because:
hasMatchingSymbol reported error: could not find implicit value for parameter gen: shapeless.Generic.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],V]
       felix.removeField('name)
       ^
<console>:15: shapeless.this.Generic.materialize is not a valid implicit value for shapeless.Generic.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],V] because:
hasMatchingSymbol reported error: No Generic instance available for HList or Coproduct
       felix.removeField('name)
       ^
<console>:15: shapeless.this.LabelledGeneric.materializeProduct is not a valid implicit value for shapeless.LabelledGeneric.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],G] because:
hasMatchingSymbol reported error: could not find implicit value for parameter gen: shapeless.Generic.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],V]
       felix.removeField('name)
       ^
<console>:15: removeField.this.RemoveField.generic is not a valid implicit value for removeField.RemoveField[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]]] because:
hasMatchingSymbol reported error: could not find implicit value for parameter gen: shapeless.LabelledGeneric.Aux[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]],G]
       felix.removeField('name)
       ^
<console>:15: shapeless.this.Lazy.mkLazy is not a valid implicit value for shapeless.Lazy[removeField.RemoveField[this.Out]] because:
hasMatchingSymbol reported error: Unable to derive removeField.RemoveField[shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("fish")],Int],shapeless.HNil]]]
       felix.removeField('name)
       ^
<console>:15: removeField.this.RemoveField.generic is not a valid implicit value for removeField.RemoveField[removeField.Cat] because:
hasMatchingSymbol reported error: could not find Lazy implicit value of type removeField.RemoveField[G]
       felix.removeField('name)
       ^
<console>:15: removeField.RemoveFieldOps is not a valid implicit value for removeField.felix.type => ?{def removeField: ?} because:
could not find implicit value for parameter removeFieldT: removeField.RemoveField[removeField.Cat]
       felix.removeField('name)
       ^
<console>:15: error: value removeField is not a member of removeField.Cat
       felix.removeField('name)
             ^

1 个答案:

答案 0 :(得分:0)

事实证明这是不可能的,所以我最后写了https://github.com/caente/equals-except