示例代码中的错误是由于没有Sprocket
定义任何子类型引起的。如果至少有 1 个子类型Sprocket
,则 Shapeless 能够生成LabelledGeneric[Sprocket]
表示为可区分联合的实例。联合是标记的子类型的副产品。
添加以下内容可解决错误:
case class Woozle(x: Int, y: Int) extends Sprocket
object Woozle {
implicit val discriminator: Discriminator[Sprocket, Woozle, Int] = Discriminator(1)
implicit val codec: Codec[Woozle] = (uint8 :: uint8).as[Woozle]
}
请注意,您需要同伴中的 thediscriminator
和codec
隐含。如果discriminator
未定义,您将收到报告的错误。如果codec
未定义,您将得到一个发散的隐式错误。从理论上讲,Woozle
如果存在隐式作用域,则编解码器可以自动派生Codec[Int]
,但 scalac 不能胜任这项任务——相反,它会因发散的隐式扩展错误而摆脱困境。我们希望通过 Shapeless 2.1 改进这一点。
供参考,完整来源:
import scalaz.\/
import shapeless._
import scodec.bits._
import scodec.codecs._
import scodec._
sealed trait Sprocket
object Sprocket {
implicit val discriminated: Discriminated[Sprocket, Int] = Discriminated(uint8)
}
case class Woozle(x: Int, y: Int) extends Sprocket
object Woozle {
implicit val discriminator: Discriminator[Sprocket, Woozle, Int] = Discriminator(1)
implicit val codec: Codec[Woozle] = (uint8 :: uint8).as[Woozle]
}
object Main extends App {
def codec(d: Int): Codec[Sprocket] = Codec.coproduct[Sprocket].discriminatedBy(provide(d)).auto
}
并构建:
scalaVersion := "2.11.4"
libraryDependencies += "org.typelevel" %% "scodec-core" % "1.5.0"