Это путаница между подчеркиванием используется в определениях параметров типа и в других местах. Подчеркивание в TypeTag[B[_]]
означает экзистенциальный тип, поэтому вы получаете тег не для B
, а для экзистенциальной оболочки поверх него, что практически бесполезно без ручной постобработки.
Следовательно, typeOf[Funct[B, _]]
, которому требуется бирка для сырья B
, не может использовать тег для обертки и расстраиваться. Из-за того, что я расстраиваюсь, я имею в виду, что он отказывается связывать тег в области видимости и терпит неудачу с ошибкой компиляции. Если вместо этого вы используете weakTypeOf
, то этот будет преуспевать, но он будет генерировать заглушки для всего, что не удалось сплайсировать, делая результат бесполезным для проверки подтипов.
Похоже, что в этом случае мы действительно попадаем в рамки Scala в том смысле, что нам не нужно ссылаться на raw B
в WeakTypeTag[B]
, потому что у нас нет доброго полиморфизма в Scala. Надеюсь, что-то вроде DOT спасет нас от этих неудобств, но пока вы можете использовать это обходное решение (это некрасиво, но я не смог придумать более простой подход).
import scala.reflect.runtime.universe._
object Test extends App {
class Foo[B[_], T]
// NOTE: ideally we'd be able to write this, but since it's not valid Scala
// we have to work around by using an existential type
// def test[B[_]](implicit tt: WeakTypeTag[B]) = weakTypeOf[Foo[B, _]]
def test[B[_]](implicit tt: WeakTypeTag[B[_]]) = {
val ExistentialType(_, TypeRef(pre, sym, _)) = tt.tpe
// attempt #1: just compose the type manually
// but what do we put there instead of question marks?!
// appliedType(typeOf[Foo], List(TypeRef(pre, sym, Nil), ???))
// attempt #2: reify a template and then manually replace the stubs
val template = typeOf[Foo[Hack, _]]
val result = template.substituteSymbols(List(typeOf[Hack[_]].typeSymbol), List(sym))
println(result)
}
test[Option]
}
// has to be top-level, otherwise the substituion magic won't work
class Hack[T]
Проницательный читатель заметит, что я использовал WeakTypeTag
в подписи foo
, хотя я должен быть в состоянии использовать TypeTag
. В конце концов, мы вызываем foo на Option
, который является хорошим типом, в том смысле, что он не включает нерешенные параметры типа или локальные классы, которые создают проблемы для TypeTag
. К сожалению, это не так просто из-за https://issues.scala-lang.org/browse/SI-7686, поэтому мы вынуждены использовать слабый тег, хотя нам и не нужно.
Для подтверждения вашего ожидания немного: 'неявно [Funct [Option, Int] <:
pedrofurla
Из https: //gist.github.com/xeno-by/6054650 Я вижу, что тип reifier не видит тега типа для B, поэтому вы не получите правильный тип из weakTypeOf [Funct [B, _]]. –
Хорошо, теперь я вижу, в чем проблема. Это снова смешение между подчеркиваниями, используемыми в определениях параметров типа и в других местах. Подчеркивание в 'TypeTag [B [_]]' означает экзистенциальный тип, поэтому вы получаете тег типа не для 'B', а для экзистенциальной оболочки поверх него. Следовательно, 'typeOf [Funct [B, _]]' не может использовать этот тег типа и расстраивается. –