2015-04-25 19 views
10

eine einfache parametrisierte Typ wie class LK[A] Da kann ichConstructing TypeTags höherer kinded Typen

// 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 

Jetzt schreibe ich möchte ein Analogon für class HK[F[_], A] schreiben:

def tagHK[F[_], A](implicit ???) = typeTag[HK[F, A]] 
// or some other implementation? 

tagHK[Option, Int] == typeTag[HK[Option, Int]] 

Ist das möglich ? Ich habe versucht,

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]] 

aber weder Werke aus den offensichtlichen Gründen (im ersten Fall F[_] ist der existentielle Typ anstelle des höheren kinded ein, in den zweiten TypeTag[F] nicht kompilieren).

Ich vermute die Antwort ist "es ist unmöglich", aber wäre sehr glücklich, wenn es nicht ist.

EDIT: Wir verwenden derzeit WeakTypeTag s wie folgt (etwas vereinfacht):

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 dies funktioniert gut, wenn wir WeakTypeTag mit TypeTag ersetzen. Leider gilt dies nicht:

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]] 
    } 
} 
+0

Does diese Hilfe? http://StackOverflow.com/a/17791973/1223622 –

+0

@BenReich Ja, tut es. Vielen Dank! –

Antwort

4

Funktioniert das für Ihre Zwecke?

def tagHK[F[_], A](implicit tt: TypeTag[HK[F, A]]) = tt 

Im Gegensatz zu den impliziten Parameter mit der TypeTag für F und A separat zu bekommen und dann komponieren sie, können Sie verlangen, direkt den Tag, das Sie vom Compiler wollen. Dies geht Ihr Testfall nach Wunsch:

tagHK[Option, Int] == typeTag[HK[Option, Int]] //true 

Alternativ, wenn Sie eine Instanz von TypeTag[A] haben könnten Sie versuchen:

object HK { 
    def apply[F[_]] = new HKTypeProvider[F] 
    class HKTypeProvider[F[_]] { 
     def get[A](tt: TypeTag[A])(implicit hktt: TypeTag[HK[F, A]]) = hktt 
    } 
} 

Sie erlauben zu tun:

val myTT = typeTag[Int] 
HK[Option].get(myTT) == typeTag[HK[Option, Int]] //true 
+0

Gute Idee, aber leider nicht ('TypeTag [A]' wird tatsächlich zur Laufzeit aus einer Datenstruktur gewonnen, nicht direkt vom Compiler eingefügt). –

+0

@AlexeyRomanov Sie haben also eine Instanz von 'TypeTag [A]'? Kannst du uns mehr darüber erzählen, wie deine Einrichtung aussieht? Ich habe hier eine Lösung hinzugefügt, wenn Sie eine Instanz von 'TypeTag [A]' haben und 'F [_]' zur Kompilierzeit wissen. –

+0

Ich habe eine Beschreibung unserer Situation zu der Frage hinzugefügt. –

Verwandte Themen