通过 LiftAll 收集实例
Collect instances via LiftAll
我正在尝试描述案例 class 包含的类型。
import shapeless._
import shapeless.ops.hlist.LiftAll
trait Desc[T] {
def description: String
}
case class Foo(f: Int)
object Foo {
implicit val description: Desc[Foo] = new Desc[Foo] { val description = "foo" }
}
case class SomeCaseClass(f: Foo)
val gen = Generic[SomeCaseClass]
val lifted = implicitly[LiftAll[Desc, gen.Repr]].instances.toList
给我
could not find implicit value for parameter toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[shapeless.ops.hlist.LiftAll[Playground.this.Desc,Playground.this.gen.Repr]#Out,List,Lub]
not enough arguments for method toList: (implicit toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[shapeless.ops.hlist.LiftAll[Playground.this.Desc,Playground.this.gen.Repr]#Out,List,Lub])toTraversableAux.Out.
Unspecified value parameter toTraversableAux.
这里是斯卡斯蒂:https://scastie.scala-lang.org/bXu71pMQQzCqrrsahVBkWA
当您使用 implicitly[LiftAll[Desc, gen.Repr]]
调用隐式实例时,LiftAll
的依赖类型 Out
将丢失,因此编译器不知道确切的类型 instances
将 return.
为了解决这个问题,Shapeless 中的大多数类型类在其伴随对象中定义了一个 apply
方法,该方法确实保留了所有相关类型信息。这就是为什么在调用 val gen = Generic[SomeCaseClass]
之后可以有意义地使用 gen.Repr
的原因。但是出于某种原因 LiftAll.apply
是 not implemented in this way。这样一来,您就可以选择实现自己的 implicitly
,或者既然您正在使用 Shapeless,请使用它的 the
,这应该是更好的 implicitly
.
scala> def impl[T <: AnyRef](implicit ev: T): ev.type = ev
impl: [T <: AnyRef](implicit ev: T)ev.type
scala> impl[LiftAll[Desc, gen.Repr]].instances.toList
res1: List[Desc[Foo]] = List(Foo$$anon@40b3708a)
scala> the[LiftAll[Desc, gen.Repr]].instances.toList
res2: List[Desc[Foo]] = List(Foo$$anon@40b3708a)
您可以在此处看到 REPL 显示的推断类型的差异:
scala> impl[LiftAll[Desc, gen.Repr]]
res3: LiftAll.Aux[Desc,Foo :: HNil,Desc[Foo] :: HNil] = shapeless.ops.hlist$LiftAll$$anon6@384d060c
scala> implicitly[LiftAll[Desc, gen.Repr]]
res4: LiftAll[Desc,gen.Repr] = shapeless.ops.hlist$LiftAll$$anon6@30787774
我正在尝试描述案例 class 包含的类型。
import shapeless._
import shapeless.ops.hlist.LiftAll
trait Desc[T] {
def description: String
}
case class Foo(f: Int)
object Foo {
implicit val description: Desc[Foo] = new Desc[Foo] { val description = "foo" }
}
case class SomeCaseClass(f: Foo)
val gen = Generic[SomeCaseClass]
val lifted = implicitly[LiftAll[Desc, gen.Repr]].instances.toList
给我
could not find implicit value for parameter toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[shapeless.ops.hlist.LiftAll[Playground.this.Desc,Playground.this.gen.Repr]#Out,List,Lub]
not enough arguments for method toList: (implicit toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[shapeless.ops.hlist.LiftAll[Playground.this.Desc,Playground.this.gen.Repr]#Out,List,Lub])toTraversableAux.Out.
Unspecified value parameter toTraversableAux.
这里是斯卡斯蒂:https://scastie.scala-lang.org/bXu71pMQQzCqrrsahVBkWA
当您使用 implicitly[LiftAll[Desc, gen.Repr]]
调用隐式实例时,LiftAll
的依赖类型 Out
将丢失,因此编译器不知道确切的类型 instances
将 return.
为了解决这个问题,Shapeless 中的大多数类型类在其伴随对象中定义了一个 apply
方法,该方法确实保留了所有相关类型信息。这就是为什么在调用 val gen = Generic[SomeCaseClass]
之后可以有意义地使用 gen.Repr
的原因。但是出于某种原因 LiftAll.apply
是 not implemented in this way。这样一来,您就可以选择实现自己的 implicitly
,或者既然您正在使用 Shapeless,请使用它的 the
,这应该是更好的 implicitly
.
scala> def impl[T <: AnyRef](implicit ev: T): ev.type = ev
impl: [T <: AnyRef](implicit ev: T)ev.type
scala> impl[LiftAll[Desc, gen.Repr]].instances.toList
res1: List[Desc[Foo]] = List(Foo$$anon@40b3708a)
scala> the[LiftAll[Desc, gen.Repr]].instances.toList
res2: List[Desc[Foo]] = List(Foo$$anon@40b3708a)
您可以在此处看到 REPL 显示的推断类型的差异:
scala> impl[LiftAll[Desc, gen.Repr]]
res3: LiftAll.Aux[Desc,Foo :: HNil,Desc[Foo] :: HNil] = shapeless.ops.hlist$LiftAll$$anon6@384d060c
scala> implicitly[LiftAll[Desc, gen.Repr]]
res4: LiftAll[Desc,gen.Repr] = shapeless.ops.hlist$LiftAll$$anon6@30787774