【问题标题】:Shapeless: How to express <: case class type param for Generix.AuxShapeless: 如何表达 <: Generix.Aux 的案例类类型参数
【发布时间】:2016-07-29 21:02:45
【问题描述】:

我有以下代码基本上遍历case class 的字段并使用Poly 将它们映射到相同类型并使用ToList[HL, Out]

为简单起见,我们可以假设Poly 这样做:

object Schema extends Poly1 {
  implicit def caseInt = at[Int](_ => "I'm an int")
  implicit def caseString = at[String](_ => "Oh boy a string")
}

def infer[V1 <: Product, Out <: HList, MapperOut <: HList](v1: V1)(
  implicit gen: Generic.Aux[V1, Out],
    map: Mapper.Aux[Schema.type, Out, MapperOut],
    to: ToList[MapperOut, String]
): List[String] = to (gen to v1 map Schema)

这一切都非常简单,非常适合简单的场景:

case class Test(id: Int, text: String)
val list = infer(Test(2, "text"))
// List("I'm an int", "Oh boy a string")

现在去公共汽车不运行的地方:

class Automagical[T <: Product with Serializable : TypeTag] {
  def instance: T 
  // The typetag bit is needed for something else
  def convert: List[String] = infer(instance)
}

遗憾的是,对上述的任何调用都失败了:

could not find implicit value for parameter gen: shapeless.Generic.Aux[T,Out]

奖金

如何通过根本不需要T 的实例来改进infer 方法?显然类型推断很好,但我确实需要以某种方式从HList[Lub] 实现List[String] 并映射一些东西。

鉴于我只关心类型,是否有可能仅通过知道要被多映射编码为HList? 的类型来派生List[String] 的具体实例

类似:

 def infer[V1 <: Product, Out <: HList, MapperOut <: HList]()(
  implicit gen: Generic.Aux[V1, Out],
    map: Mapper.Aux[Schema.type, Out, MapperOut],
    to: ToList[MapperOut, String]
): List[String] = {
  // Magically build an HList with samples from its types.
  // Or an alternative approach that gives the same outcome
  val reifiedInstance = reify[Out]
  to (reifiedInstance map Schema)
}

【问题讨论】:

  • Automagical trait 无法为我编译:“traits cannot have type parameters with context bounds”,但你提到的错误当然也发生在抽象类中。
  • @devkat 我的错,那是原始实现中的一个类。

标签: scala shapeless


【解决方案1】:

为确保convert 可以访问infer 的隐式参数,它们必须在Automagical 实例创建时出现:

abstract class Automagical[T <: Product with Serializable : TypeTag,
    Out <: HList, MapperOut <: HList]
  (implicit
    gen: Generic.Aux[T, Out],
    map: Mapper.Aux[Schema.type, Out, MapperOut],
    to: ToList[MapperOut, String]) {
  def instance: T
  // The typetag bit is needed for something else
  def convert: List[String] = infer(instance)
}

【讨论】:

  • 这对我来说是不行的,因为我需要 Automagical 成为一个类型类。
  • 我接受了这个答案,因为它解决了那个特定的问题。有什么方法可以处理你所知道的不需要实例的事情吗?
  • scalacheck-shapeless (github.com/alexarchambault/scalacheck-shapeless) 可以为案例类创建示例实例,可能通过HLists。也许值得看看它是如何在那里完成的。
猜你喜欢
  • 1970-01-01
  • 2016-09-17
  • 2023-03-23
  • 1970-01-01
  • 2019-03-04
  • 1970-01-01
  • 2018-02-17
  • 2020-12-20
  • 1970-01-01
相关资源
最近更新 更多