Retrieving a value of this type from the case class

Is it possible, using Shapeless, to extract a value of a specific type from the case class? So far I can do this:

def fromCaseClass[T, R <: HList](value: T)(implicit ga: Generic.Aux[T, R]): R = {
  ga.to(value)
}

Which then allows me to retrieve the values ​​procedurally:

scala> case class ServiceConfig(host: String, port: Int, secure: Boolean)
defined class ServiceConfig

scala> val instance = ServiceConfig("host", 80, true)
instance: ServiceConfig = ServiceConfig(host,80,true)

scala> fromCaseClass(instance).select[Boolean]
res10: Boolean = true

scala> fromCaseClass(instance).select[Int]
res11: Int = 80

However, when I try to write a function to do this, I become attached to implications that were not found:

def getByType[C, X](value: C)(implicit ga: Generic.Aux[C, X]): X = {
  fromCaseClass(value).select[X]
}

<console>:12: error: could not find implicit value for parameter ga: shapeless.Generic.Aux[C,R]
       fromCaseClass(value).select[X]

Presumably, I get this because the compiler cannot verify that my parameter is not a case class. Is there any way to do this?

I am completely new to Shapeless, so I'm not quite sure if I am trying to do something crazy or miss something simple.

Update

I feel like I'm getting a little closer. I can implement like this:

def newGetByType[C, H <: HList, R]
     (value: C)
     (implicit ga: Generic.Aux[C, H], selector: Selector[H, R]): R = {
  ga.to(value).select[R]
}

And this allows me to choose from the case class:

scala> val s: String = newGetByType(instance)
s: String = host

But this seems to work only for the first type in the case class:

scala> val i: Int = newGetByType(instance)
<console>:17: error: type mismatch;
 found   : String
 required: Int
       val i: Int = newGetByType(instance)

Am I on the right track?

+4
2

...

newGetByType , , (, , val LHS , ).

, ? ,

def getByType[S, C, L <: HList](value: C)
  (implicit gen: Generic.Aux[C, L], sel: Selector[L, S]): S =
    gen.to(value).select[S]

S, C value L C. , , Scala ... .

, , , , : , , , : , , .

, , , ,

class GetByType[S] {
  def apply[C, L <: HList](value: C)
    (implicit gen: Generic.Aux[C, L], sel: Selector[L, S]): S =
      gen.to(value).select[S]
}

, , S , apply . getByType, , , ,

def getByType[S] = new GetByType[S]

, ,

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

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

class GetByType[S] {
  def apply[C, L <: HList](value: C)
    (implicit gen: Generic.Aux[C, L], sel: Selector[L, S]): S =
      gen.to(value).select[S]
}

// Exiting paste mode, now interpreting.

defined class GetByType

scala> def getByType[S] = new GetByType[S]
getByType: [S]=> GetByType[S]

scala> case class ServiceConfig(host: String, port: Int, secure: Boolean)
defined class ServiceConfig

scala> val instance = ServiceConfig("host", 80, true)
instance: ServiceConfig = ServiceConfig(host,80,true)

scala> getByType[String](instance)
res0: String = host

scala> getByType[Int](instance)
res1: Int = 80

scala> getByType[Boolean](instance)
res2: Boolean = true
+7

, ga , (.. fromCaseClass):

def getByType[C, X](value: C)(implicit ga: Generic.Aux[C, X]): X = {
  fromCaseClass(value)(ga).select[X]
}

, fromCaseClass:

def getByType[C, X](value: C)(implicit ga: Generic.Aux[C, X]): X = {
    val innerGa = ga
    fromCaseClass(value).select[X]
}
0

All Articles