避免使用无形结构的结构类型

时间:2015-08-18 16:12:30

标签: scala shapeless

我想知道某个特定的成员是否存在于给定的case class中。

以下确实给了我答案,在编译时失败,这是正确的。 (信用Travis Brown)

scala>  def getIntId[A, R <: HList](a: A)(implicit
 |   gen: LabelledGeneric.Aux[A, R],
 |   sel: Selector.Aux[R, Witness.`'id`.T, Int]
 | ): Int = sel(gen.to(a))

 case class Foo(id: String)
 case class Bar(id: Int, name: String)

scala> getIntId(Bar(123, "bar"))
res3: Int = 123

scala> getIntId(Foo("12345"))
<console>:15: error: could not find implicit value for parameter sel:    shapeless.ops.record.Selector.Aux[R,Symbol with shapeless.tag.Tagged[String("id")],Int]
          getIntId(Foo("12345"))

现在,如果我没有具体类型但T传递给getIntId方法,有没有办法让它与泛型类型T一起使用?

更新 假设有一个名为findIdFromType的方法,如下所述,它采用T类型(其中T将始终为某个case class)。是否有可能使这项工作?

def findIdFromType[T](t:T) = {
  getIntId(t) //as expected doesn't compile
}

1 个答案:

答案 0 :(得分:2)

getIntId需要两个隐式参数。

如果需要在本地方法的上下文中调用它,则需要证明这些参数存在于此类上下文中。

为了做到这一点,你必须传播隐含的证据,比如

def findIdFromType[A, R <: HList](a: A)(implicit
  gen: LabelledGeneric.Aux[A, R],
  sel: Selector.Aux[R, Witness.`'id`.T, Int]): Int = getIntId(a)

这当然是一个完全没用的例子,但是如果你想在包装方法中执行其他操作,这就是要走的路:传播隐式证据。