Given a simple parametrized type like class LK[A]
, I can write
// or simpler def tagLK[A: TypeTag] = typeTag[LK[A]]
def tagLK[A](implicit tA: TypeTag[A]) = typeTag[LK[A]]
tagLK[Int] == typeTag[LK[Int]] // true
Now I'd like to write an analogue for class HK[F[_], A]
:
def tagHK[F[_], A](implicit ???) = typeTag[HK[F, A]]
// or some other implementation?
tagHK[Option, Int] == typeTag[HK[Option, Int]]
Is this possible? I've tried
def tagHK[F[_], A](implicit tF: TypeTag[F[_]], tA: TypeTag[A]) = typeTag[HK[F, A]]
def tagHK[F[_], A](implicit tF: TypeTag[F], tA: TypeTag[A]) = typeTag[HK[F, A]]
but neither works for the obvious reasons (in the first case F[_]
is the existential type instead of the higher-kinded one, in the second TypeTag[F]
doesn't compile).
I suspect the answer is "it's impossible", but would be very happy if it isn't.
EDIT: we currently use WeakTypeTag
s as follows (slightly simplified):
trait Element[A] {
val tag: WeakTypeTag[A]
// other irrelevant methods
}
// e.g.
def seqElement[A: Element]: Element[Seq[A]] = new Element[Seq[A]] {
val tag = {
implicit val tA = implicitly[Element[A]].tag
weakTypeTag[Seq[A]]
}
}
trait Container[F[_]] {
def lift[A: Element]: Element[F[A]]
// note that the bound is always satisfied, but we pass the
// tag explicitly when this is used
def tag[A: WeakTypeTag]: WeakTypeTag[F[A]]
}
val seqContainer: Container[Seq] = new Container[Seq] {
def lift[A: Element] = seqElement[A]
}
All of this works fine if we replace WeakTypeTag
with TypeTag
. Unfortunately, this doesn't:
class Free[F[_]: Container, A: Element]
def freeElement[F[_]: Container, A: Element] {
val tag = {
implicit val tA = implicitly[Element[A]].tag
// we need to get something like TypeTag[F] here
// which could be obtained from the implicit Container[F]
typeTag[Free[F, A]]
}
}
Does this serve your purposes?
def tagHK[F[_], A](implicit tt: TypeTag[HK[F, A]]) = tt
As opposed to using the implicit parameter to get the TypeTag
for F
and A
separately and then composing them, you can directly request the tag you want from the compiler. This passes your test case as desired:
tagHK[Option, Int] == typeTag[HK[Option, Int]] //true
Alternatively, if you have an instance of TypeTag[A]
you could try:
object HK {
def apply[F[_]] = new HKTypeProvider[F]
class HKTypeProvider[F[_]] {
def get[A](tt: TypeTag[A])(implicit hktt: TypeTag[HK[F, A]]) = hktt
}
}
Allowing you to do:
val myTT = typeTag[Int]
HK[Option].get(myTT) == typeTag[HK[Option, Int]] //true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With