由于 class 具有非值字段,因此缺少 scodec.Codec[Command]

Missing scodec.Codec[Command] implicit because of class with non-value fields

我正在尝试在现有项目中使用鉴别器,我想我的 类 有问题。

考虑这个 scodec example。如果我将 TurnLeft 及其编解码器更改为

sealed class TurnLeft(degrees: Int) extends Command {
  def getDegrees: Int = degrees
}
implicit val leftCodec: Codec[TurnLeft] = uint8or16.xmap[TurnLeft](v => new TurnLeft(v), _.getDegrees)

我明白了

Error:(x, x) could not find Lazy implicit value of type scodec.Codec[Command]
    val codec: Codec[Either[UnrecognizedCommand, Command]] = discriminatorFallback(unrecognizedCodec, Codec[Command])

如果我创建 degrees 字段值字段,一切都有效。我怀疑这是无形的棘手问题。我应该怎么做才能让它发挥作用?

演示该问题的示例项目是 here

shapeless 的 Generic 是为 "case-class-like" 类型定义的。对于第一个近似值,case-class-like 类型的值可以被解构为其构造函数参数,然后可用于重建一个相等的值,即

case class Foo ...
val foo = Foo(...)
val fooGen = Generic[Foo]
assert(fooGen.from(fooGen.to(foo)) == foo)

具有单个构造函数参数列表的案例 类 满足此条件,而 类 其构造函数参数没有 public(惰性)vals,或伴随匹配apply/unapply,不要。

Generic 的实现是相当宽松的,并且会将对应于构造函数参数(按类型和顺序)的(惰性)val 成员视为等同于可访问的构造函数参数,因此最接近您的示例我们可以得到的是这样的,

sealed class TurnLeft(degrees: Int) extends Command {
  val getDegrees: Int = degrees
}

scala> Generic[TurnLeft]
res0: shapeless.Generic[TurnLeft]{type Repr = Int :: HNil } = ...

在这种情况下,getDegrees 被视为单个 Int 构造函数参数的访问器。