传递一个类型参数以用作参数LabelledGeneric

时间:2014-12-13 00:44:56

标签: scala shapeless labelled-generic

我正在尝试参数化一个需要处理可以检索A的泛型LabelledGeneric的方法。这是天真的方法

case class Foo(bar: String, baz: Boolean)

def params[A](a: A) = {
  val lbl = LabelledGeneric[A]
  val keys = Keys[lbl.Repr].apply
  ...
}

val myThingy = params(Foo)

当然,潜在的宏抱怨。它对A

的了解不够
  

类型A不是类或特征


所以,我试图推断LabelledGeneric

def params[A](a: A)(implicit lbl: LabelledGeneric[A]) = {
  val keys = Keys[lbl.Repr].apply
  ...
}

这似乎有效,但Repr类型不再是HList

  

类型参数[lbl.Repr]不符合方法apply的类型参数bounds [L<:shapeless.HList]


好的,让我们试着更精确

def params[A, Repr <: HList](a: A)(implicit lbl: LabelledGeneric.Aux[A, Repr]) = {
  val keys = Keys[lbl.Repr].apply
  ...
}

现在,Repr绝对是HList,但Keys无法解决其含义

  

无法找到参数值的隐含值:shapeless.ops.record.Values [lbl.Repr]


最后的尝试,让我们试着让我需要的东西隐含地计算

def params[A, Repr <: HList](a: A)(implicit
  lbl: LabelledGeneric.Aux[A, Repr],
  kk: Keys[Repr]
) = {
  val keys = kk.apply
  ...
}

仍然没有运气,显然第一个隐含的无法在呼叫站点解决

  

找不到参数lbl的隐含值:shapeless.LabelledGeneric.Aux [example.Main.Foo.type,Repr]

     

[错误] params(Foo)

显然,当直接处理特定类型时,所有这些机器都可以工作,例如

val lbl = LabelledGeneric[Foo]
val keys = Keys[lbl.Repr].apply
// no problem

我在方法签名中明显缺少我的类型所需的一组优化,但我可以了解这里发生的事情。有什么想法吗?

1 个答案:

答案 0 :(得分:5)

包含所有计算内容的最后一个变体对我有效,

scala> import shapeless._, ops.record._
import shapeless._
import ops.record._

scala> :paste
// Entering paste mode (ctrl-D to finish)

def params[A, Repr <: HList](a: A)
  (implicit lbl: LabelledGeneric.Aux[A, Repr], kk: Keys[Repr]) = {
  val keys = kk.apply
  keys
}

// Exiting paste mode, now interpreting.

params: ...

scala> case class Foo(bar: String, baz: Boolean)
defined class Foo

scala> params(foo)
res0: ... = 'bar :: 'baz :: HNil

(为了便于阅读,省略了结果类型。)