Vikas Pandya
Vikas Pandya

Reputation: 1988

Avoid structural type with shapeless alternative

I want to find out if a particular class member is present in a given case class or not.

Following does give me that answer, failing at compile time which is right. (credit to 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"))

Now if I don't have a concrete type but T to pass into getIntId method, is there a way to get this to work with generic type T ?

Update Say have a method called findIdFromType as described below which takes in type T (where T will always be a some case class). is it possible to make this work?

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

Upvotes: 0

Views: 421

Answers (1)

Gabriele Petronella
Gabriele Petronella

Reputation: 108101

getIntId requires two implicit parameters.

If you need to call it in the context of a local method, you need to prove that those parameters exist in such context.

In order to do so, you have to propagate the implicit evidence, like this

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

This of course is a completely useless example, but in case you want to perform other operations inside the wrapping method, this is the way to go: propagate the implicit evidence.

Upvotes: 2

Related Questions