【问题标题】:LabelledGeneric instance generation on a tagged case class yields me an error in shapeless标记案例类上的 LabelledGeneric 实例生成给我一个无形错误
【发布时间】:2016-07-20 12:58:16
【问题描述】:

我试图从来自另一个 HList(确切地说是另一个 LabelledGeneric)的标记类型中获取一个 LabelledGeneric 实例,但编译器给我一个错误,说它找不到隐式。

确切的错误是(启用-x-log-implicits):

shapeless.this.DefaultSymbolicLabelling.mkDefaultSymbolicLabelling is not a valid implicit value for shapeless.DefaultSymbolicLabelling.Aux[Inner with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("c")],Inner],K] because:
hasMatchingSymbol reported error: Inner with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("c")],Inner] is not case class like or the root of a sealed family of types

这是sn-p:

case class Inner(a: Int)
case class Outer(b: Int, c: Inner)

val gen = LabelledGeneric[Outer]

val inner = Inner(1)
val outer = Outer(2, inner)

def getGen[A, L](x: A)(implicit gen: LabelledGeneric.Aux[A, L]) = gen

val hOuter = gen.to(outer)

getGen(hOuter.at(1))

我在这里遗漏了什么明显的东西吗?

谢谢。

编辑:

我添加了案例类的定义。我也在使用 scala 2.11.8 和 shapeless 2.3.0

【问题讨论】:

  • 您能否包括OuterInner 的定义,并说明您正在使用哪些版本的shapeless 和scalac。
  • 我已将它们添加到问题中

标签: scala generic-programming shapeless


【解决方案1】:

LabelledGeneric[Outer]Outer 类型的值放入无形记录中。这些是HLists 个字段,每个字段都是一个带有“标签”标签的值……一个对应于案例类中字段名称的单例类型。 T 类型的标记值是 T 类型的子类型,但两种类型不相同。通常这绝对没问题。

在您的场景中,您将采用hOuter.at(1) 类型的字段FieldType['c.type, Inner]。这是一个类型别名,它扩展为以下满口,

Inner with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("c")],Inner]

然后您请求与该类型对应的LabelledGeneric 实例。不幸的是,虽然Inner 有一个LabelledGeneric 实例,但FieldType['c.type, Inner] 没有实例,因为正如编译器错误消息所说(wrt 扩展类型),

Inner with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("c")],Inner]
is not case class like or the root of a sealed family of types

如果您实际上并没有将标签用于任何事情,那么最简单的解决方法是在整个过程中使用Generic 而不是LabelledGeneric,或者至少在gen 的定义中使用。

如果您使用标签,那么解决问题的方法是将它们从字段中剥离。做到这一点的最简单的方法是依赖 InnerFieldType['c.type, Inner] 的子类型并使用类型归属,

getGen(hOuter.at(1): Inner)

这意味着getGen的类型参数A将被推断为Inner,并且对LabelledGeneric[A]的隐式查找将成功。

更通用的解决方案是使用 shapeless 的 Values 类型类,该类采用无形记录并从其每个元素上剥离标签,从而生成仅包含值的 HList

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多