gpt4 book ai didi

scala - 使用带有 LabelledGenerics 的无形状标签

转载 作者:行者123 更新时间:2023-12-04 08:55:04 24 4
gpt4 key购买 nike

假设我想按照 here 的描述遍历 case 类的通用表示

我定义了一些类型类来描述字段:

trait Described[X] extends (X => String)
object Described{
def apply[X](x: X)(implicit desc: Described[X]) = desc(x)
}

定义了一些实例:
implicit object DoubleDescribed extends Described[Double]{
def apply(x: Double) = x.formatted("%01.3f")
}

和一般用户:
import shapeless._
import shapeless.labelled.FieldType
import shapeless.ops.hlist.LeftFolder

object DescrFolder extends Poly2{
implicit def field[X, S <: Symbol](implicit desc: Described[X],
witness: Witness.Aux[S]):
Case.Aux[Seq[String], FieldType[S, X], Seq[String]] =
at[Seq[String], FieldType[S, X]](
(descrs, value) => descrs :+ f"${witness.value.name}: ${desc(value)}")
}

def describe[T <: Product, Repr <: HList](struct: T)
(implicit lgen: LabelledGeneric.Aux[T,Repr],
folder: LeftFolder.Aux[Repr, Seq[String], DescrFolder.type, Seq[String]]
): String = {
val repr = lgen.to(struct)
val descrs = folder(repr,Vector())
descrs.mkString(struct.productPrefix + "{", ",", "}")
}

所以现在我可以写
case class Point(x: Double, y: Double, z: Double)
describe(Point(1,2,3.0))

并得到

res1: String = Point{x: 1,000,y: 2,000,z: 3,000}



现在我想使用 shapeless 定义一些字段元数据标签:
import tag._
trait Invisible
val invisible = tag[Invisible]
implicit def invisibleDescribed[X](implicit desc: Described[X])
: Described[X @@ Invisible] =
new Described[X @@ Invisible]{
def apply(x: X @@ Invisible) = desc(x: X) + "[invisible]"
}

所以 Described(invisible(0.5))现在成功生产

res2: String = 0,500[invisible]



但随着重新定义
case class Point(x: Double, y: Double, z: Double @@ Invisible)

describe(Point(1,2,invisible(3.0)))

产生编译错误:

Error: diverging implicit expansion for type LeftFolder.Aux[this.Out,Seq[String],DescrFolder.type,Seq[String]] starting with method invisibleDescribed in class ...



我认为该类型 X with Tag[Y] with KeyTag[K,X]未识别为 FieldType[S, X]但无法猜测如何修复它。

如何定义合适的 LeftFolder对于这种情况?

最佳答案

您的问题不涉及shapeless根本。其实可以简化为:

trait Described[T]
trait Invisible

implicit val doubleDescribed: Described[Double] = ???

implicit def invisibleDescribed[T](
implicit desc: Described[T]
): Described[T with Invisible] = ???

implicitly[Described[Double with Invisible]]
Double @@ Invisible可以“表示”为 Double with Invisible .请注意 Double with Invisible <: Double .

当编译器尝试获取隐式 Described[Double with Invisible] 时它正确地提示发散的隐式扩展: doubleDescribedinvisibleDescribed .

回到你的原始代码,一个简单的解决方法是重写 invisibleDescribed作为:

implicit def invisibleDescribed[X, I <: X @@ Invisible](
implicit desc: Described[X]
): Described[I] = new Described[I]{
def apply(x: I) = desc(x: X) + "[invisible]"
}

关于scala - 使用带有 LabelledGenerics 的无形状标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32250845/

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