当尝试使用 Shapeless 将 Map 转换为 scala 对象时,编译器不会拾取余积导数

问题描述 投票:0回答:1

我正在尝试将

Map[String, AttributeValue]
转换为 Scala 对象。
AttributeValue
代表 DynamoDB 中的数据。下面存根中的
FromAttributeValue
用于转换基本情况

以下是代码存根:

trait FromMap[L] {
  def apply(m: Map[String, AttributeValue]): Option[L]
}

object FromMap extends LowerPriorityFromMapInstances {

  implicit val hnilFromMap: FromMap[HNil] = ???

  implicit def hconsFromMap0[K <: Symbol, V, T <: HList](implicit
      witness: => Witness.Aux[K],
      fromAttributeValue: => Lazy[FromAttributeValue[V]],
      fromMapT: => FromMap[T],
  ): FromMap[FieldType[K, V] :: T] = ???

  implicit def cnilFromMap: FromMap[CNil] = ???

  implicit def coproductFromMap[K <: Symbol, H, T <: Coproduct](implicit 
      wit: => Witness.Aux[K],
      fromMapH: => Lazy[FromMap[H]],
      fromMapT: => FromMap[T]
  ): FromMap[FieldType[K, H] :+: T] = ???
}

trait LowerPriorityFromMapInstances {

//Other instances as required


  implicit def hConsFromMap1[K <: Symbol, V, R <: HList, T <: HList](implicit
      wit: => Witness.Aux[K],
      gen: => LabelledGeneric.Aux[V, R],
      fromMapH: => Lazy[FromMap[R]],
      fromMapT: => FromMap[T]
  ): FromMap[FieldType[K, V] :: T] = ???
 
}

以下是相同的scastie

编译器能够找到除密封特征之外的所有情况的派生。我怎样才能做到这一点?

scala typeclass shapeless
1个回答
0
投票

首先,由于你的表示类型现在不仅是

HList
,还有
Coproduct
,你应该删除这两个地方的上限
<: HList

implicit class FromMapOps[L /*<: HList*/](val a: Map[String, AttributeValue]) extends AnyVal { ...
implicit def hConsFromMap1[K <: Symbol, V, R /*<: HList*/, T <: HList](implicit ...

其次,在

implicit class FromMapOps
中,您将递归逻辑与扩展方法的定义混合在一起,因此您实际上并未为案例类(和密封特征)定义类型类
FromMap
的实例。但是如果你开始解决
Map.empty[String, AttributeValue].toObj[ContainerUser]
那么你会发现你需要这样的实例,即
FromMap
代表
GroupContainer

Map.empty[String, AttributeValue].toObj[ContainerUser]

implicitly[FromMap[FieldType[Witness.`'GroupContainer`.T, GroupContainer] :+: CNil]](
    FromMap.coproductFromMap(
      implicitly[Witness.Aux[Witness.`'GroupContainer`.T]],
      Lazy(implicitly[FromMap[GroupContainer]]),
      implicitly[FromMap[CNil]]
    )
  )

implicitly[FromMap[GroupContainer]]

因此,最好不要将递归逻辑与定义扩展方法的逻辑混合在一起,将定义类型类实例的逻辑和定义扩展方法的逻辑分开。尝试定义一个类型为 class 的实例

implicit def genericFromMap[A, L](implicit
                                      gen: => LabelledGeneric.Aux[A, L],
                                      fromMap: => FromMap[L],
                                 ): FromMap[A] = ???

以及扩展方法

implicit class FromMapOps[L](val a: Map[String, AttributeValue]) extends AnyVal {
  def toObj[A](implicit
                fromMap: FromMap[A]
              ): Option[A] = fromMap(a)
}

https://scastie.scala-lang.org/DmytroMitin/JwhJuXiXRBOT08RjZyywKg/2

NotImplementedError
表示代码已编译。)

您可以找到几个有关案例类和映射之间转换的问题(搜索 案例类到映射 scala映射到案例类 scala)。

© www.soinside.com 2019 - 2024. All rights reserved.