Taig
Taig

Reputation: 7298

Summoning an HList of type classes

Given an arbitrary case class Cc( a: String, b: Int ) and a type class trait Tc[T], is there a way to materialize a simple HList (or preferably a labelled record) that contains a type class instance for each parameter of Cc?

def resolveTypeClasses[C] = ???
val resolved: Tc[String] :: Tc[Int] :: HNil = resolveTypeClasses[Cc]

Upvotes: 3

Views: 138

Answers (1)

Odomontois
Odomontois

Reputation: 16328

It's hard to make single type parameter function because of need to resolve intermediate Generic.

So from my noob point of view it should be two parameter def, or sequence of two defs, each taking single type parameter. Second variant could be implemented like:

import shapeless._
trait Tc[T]

case class Cc(a: String, b: Int)

trait ResolveTC[L] {
  type Out <: HList
  val out: Out
}

implicit object ResolveHNilTC extends ResolveTC[HNil] {
  type Out = HNil
  val out: HNil = HNil
}

implicit def resolveHListTC[X, XS <: HList](implicit tc: Tc[X], rest: ResolveTC[XS]) =
  new ResolveTC[X :: XS] {
    type Out = Tc[X] :: rest.Out
    val out = tc :: rest.out
  }

class TCResolver[C] {
  def get[L <: HList](implicit gen: Generic.Aux[C, L], resolve: ResolveTC[L]): resolve.Out = resolve.out
}

def resolveTypeClasses[C] = new TCResolver[C]

implicit case object StringInst extends Tc[String]
implicit case object IntInst extends Tc[Int]

with that implementation

val resolved = resolveTypeClasses[Cc].get

will produce the

StringInst :: IntInst :: HNil

Upvotes: 3

Related Questions