【问题标题】:Compiler cannot find right implicits for shapeless LabelledGeneric编译器无法为无形 LabelledGeneric 找到正确的隐式
【发布时间】:2015-07-26 23:02:12
【问题描述】:

继续讨论转换case classesMap[String,Any],当我想以通用方式使用它时遇到了一些问题,Here 是主要讨论。

当我想使用如下的泛型方法时,编译器会抱怨隐含:

import MapConvertor._
def convert[A](cc: A)= {
    cc.toMapRec
}

这是提供toMapRec的完整代码:

import shapeless._, labelled.FieldType, record._

trait ToMapRec[L <: HList] { def apply(l: L): Map[String, Any] }

trait LowPriorityToMapRec {
  implicit def hconsToMapRec1[K <: Symbol, V, T <: HList](implicit
                                                          wit: Witness.Aux[K],
                                                          tmrT: ToMapRec[T]
                                                           ): ToMapRec[FieldType[K, V] :: T] =
    new ToMapRec[FieldType[K, V] :: T] {

      def apply(l: FieldType[K, V] :: T): Map[String, Any] =
        tmrT(l.tail) + (wit.value.name -> l.head)
  }
}

object ToMapRec extends LowPriorityToMapRec {
  implicit val hnilToMapRec: ToMapRec[HNil] = new ToMapRec[HNil] {
    def apply(l: HNil): Map[String, Any] = Map.empty
  }

  implicit def hconsToMapRec0[K <: Symbol, V, R <: HList, T <: HList](implicit
                                                                      wit: Witness.Aux[K],
                                                                      gen: LabelledGeneric.Aux[V, R],
                                                                      tmrH: ToMapRec[R],
                                                                      tmrT: ToMapRec[T]
                                                                       ): ToMapRec[FieldType[K, V] :: T] = new ToMapRec[FieldType[K, V] :: T] {
    def apply(l: FieldType[K, V] :: T): Map[String, Any] =
      tmrT(l.tail) + (wit.value.name -> tmrH(gen.to(l.head)))
  }
}

object MapConvertor {

  implicit class ToMapRecOps[A](val a: A) extends AnyVal {
    def toMapRec[L <: HList](implicit
                             gen: LabelledGeneric.Aux[A, L],
                             tmr: ToMapRec[L]
                              ): Map[String, Any] = tmr(gen.to(a))
  }

}

【问题讨论】:

    标签: scala generic-programming shapeless


    【解决方案1】:

    您需要证明代表A 的记录具有ToMapRec 实例,您可以这样做:

    def convert[A, R <: HList](cc: A)(implicit
      gen: LabelledGeneric.Aux[A, R],
      tmr: ToMapRec[R]
    ) = tmr(gen.to(cc))
    

    您还可以引入一个新的类型类来稍微清理一下:

    trait CcToMapRec[A] { def apply(a: A): Map[String, Any] }
    
    object CcToMapRec {
      implicit def ccToMapRec[A, R <: HList](implicit
        gen: LabelledGeneric.Aux[A, R],
        tmr: ToMapRec[R]
      ): CcToMapRec[A] = new CcToMapRec[A] {
        def apply(a: A): Map[String, Any] = tmr(gen.to(a))
      }
    }
    

    然后你的方法只需要一个隐式参数:

    def convert[A](cc: A)(implicit ctmr: CcToMapRec[A]) = ctmr(cc)
    

    但是您仍然需要通过任何具有您打算转换的泛型类型的方法来线程化此实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-21
      • 2020-12-06
      • 2019-05-16
      • 2013-02-08
      • 1970-01-01
      • 2012-12-19
      • 1970-01-01
      • 2012-10-21
      相关资源
      最近更新 更多