gpt4 book ai didi

scala - Shapeless 在测试中找不到隐式,但可以在 REPL 中找到

转载 作者:行者123 更新时间:2023-12-04 18:03:34 34 4
gpt4 key购买 nike

我有一个看起来像这样的案例类:

case class Color(name: String, red: Int, green: Int, blue: Int)

我在 Scala 2.11.8 中使用 Shapeless 2.3.1。在查找 LabelledGeneric[Color] 的隐含值方面,我发现我的测试和 REPL 有不同的行为。 . (我实际上是在尝试自动派生一些其他类型类,但我也得到了 null)

内测
package foo

import shapeless._
import org.specs2.mutable._

case class Color(name: String, red: Int, green: Int, blue: Int)

object CustomProtocol {
implicit val colorLabel: LabelledGeneric[Color] = LabelledGeneric[Color]
}

class GenericFormatsSpec extends Specification {
val color = Color("CadetBlue", 95, 158, 160)

"The case class example" should {
"behave as expected" in {
import CustomProtocol._
assert(colorLabel != null, "colorLabel is null")
1 mustEqual 1
}
}
}

此测试失败,因为 colorLabelnull .为什么?

复制代码

从 REPL 中,我可以找到 LabelledGeneric[Color] :
scala> case class Color(name: String, red: Int, green: Int, blue: Int)
defined class Color

scala> import shapeless._
import shapeless._

scala> LabelledGeneric[Color]
res0: shapeless.LabelledGeneric[Color]{type Repr = shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("red")],Int],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("green")],Int],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("blue")],Int],shapeless.HNil]]]]} = shapeless.LabelledGeneric$$anon$1@755f11d9

最佳答案

null您所看到的确实是带有和不带有显式注释类型的隐式定义语义的一个令人惊讶的结果。定义右侧的表达式,LabelledGeneric[Color] , 是 apply 的电话方法在 object LabelledGeneric带类型参数 Color它本身需要一个类型为 LabelledGeneric[Color] 的隐式参数.隐式查找规则意味着具有最高优先级的相应范围内隐式定义是 implicit val colorLabel目前正在定义中,即。我们有一个循环,其结果是默认值 null初始化程序。如果,OTOH,类型注释被忽略,colorLabel不在范围内,你会得到你期望的结果。这是不幸的,因为正如您正确地观察到的那样,我们应该尽可能明确地注释隐式定义。

无形的cachedImplicit提供了一种解决这个问题的机制,但在描述它之前,我需要指出一个额外的复杂性。型号LabelledGeneric[Color]不是 colorLabel 的正确类型. LabelledGeneric有类型成员 Repr这是您正在实例化的类型的表示类型 LabelledGeneric因为,并且通过对定义进行注释,您明确地放弃了 LabelledGeneric[Color] 的细化。其中包括。结果值将无用,因为它的类型不够精确。使用正确的类型注释隐式定义,或者使用显式细化或使用等效的 Aux很难,因为表示类型很难明确写出,

object CustomProtocol {
implicit val colorLabel: LabelledGeneric.Aux[Color, ???] = ...
}

同时解决这两个问题是一个两步过程,
  • 获取 LabelledGeneric具有完全精炼类型的实例。
  • 使用显式注释定义缓存的隐式值,但不生成导致 null 的初始化循环.

  • 最终看起来像这样,
    object CustomProtocol {
    val gen0 = cachedImplicit[LabelledGeneric[Color]]
    implicit val colorLabel: LabelledGeneric.Aux[Color, gen0.Repr] = gen0
    }

    关于scala - Shapeless 在测试中找不到隐式,但可以在 REPL 中找到,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37367414/

    34 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com