2015-04-25 1 views
10

Предоставлено простой параметризованная типа как class LK[A], я могу написатьПостроение TypeTags высших kinded типов

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

Теперь я хотел бы написать аналог для class HK[F[_], A]:

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

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

Возможно ли это ? Я попытался

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

но ни работы по очевидным причинам (в первом случае F[_] экзистенциальный тип вместо высшего kinded один, во втором TypeTag[F] не компилируется).

Я подозреваю, что ответ «это невозможно», но был бы очень рад, если это не так.

EDIT: в настоящее время мы используем WeakTypeTag S следующим образом (несколько упрощенно):

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

Все это прекрасно работает, если заменить WeakTypeTag с TypeTag. К сожалению, это не так:

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

Поможет ли это? http://stackoverflow.com/a/17791973/1223622 –

+0

@BenReich Да, это так. Спасибо! –

ответ

4

Это служит вашим целям?

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

В отличии от использования неявного параметра, чтобы получить TypeTag для F и A отдельно, а затем компонуют их, вы можете напрямую запрашивать метку вы хотите от компилятора. Это проходит тестовый случай, по желанию:

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

В качестве альтернативы, если у вас есть экземпляр TypeTag[A] вы можете попробовать:

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

Позволяя сделать:

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

Хорошая идея, но, к сожалению, ее нет ('TypeTag [A]' фактически получен из структуры данных во время выполнения, не вставлен непосредственно компилятором). –

+0

@AlexeyRomanov Итак, у вас есть экземпляр 'TypeTag [A]'? Не могли бы вы рассказать нам больше о том, как выглядит ваша настройка? Я добавил решение здесь, когда у вас есть экземпляр 'TypeTag [A]' и знаю 'F [_]' во время компиляции. –

+0

Я добавил описание нашей ситуации к вопросу. –

Смежные вопросы