E 'il disguido tra sottolineatura utilizzato nelle definizioni dei parametri di tipo e altrove. Il carattere di sottolineatura in TypeTag[B[_]]
indica un tipo esistenziale, quindi si ottiene un tag non per B
, ma per un wrapper esistenziale su di esso, che è praticamente inutile senza post-elaborazione manuale.
Di conseguenza typeOf[Funct[B, _]]
che necessita di un tag per raw B
non può utilizzare il tag per il wrapper e si arrabbia. Rimanendo sconvolto intendo che si rifiuta di unire il tag in scope e fallisce con un errore di compilazione. Se si utilizza invece weakTypeOf
, questo avrà esito positivo, ma genererà stub per tutto ciò che non può essere unito, rendendo il risultato inutile per i controlli di sottotitoli.
Sembra che in questo caso siamo davvero nei limiti di Scala nel senso che non è possibile per noi fare riferimento a B
in WeakTypeTag[B]
, perché non abbiamo il polimorfismo gentile in Scala. Speriamo che qualcosa come DOT ci salvi da questo inconveniente, ma nel frattempo puoi usare questa soluzione alternativa (non è carina, ma non sono riuscito a trovare un approccio più semplice).
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]
Un lettore attento avrà notato che ho usato WeakTypeTag
nella firma di foo
, anche se dovrei essere in grado di utilizzare TypeTag
. Dopo tutto, chiamiamo foo su un Option
che è un tipo ben educato, nel senso che non coinvolge parametri di tipo irrisolti o classi locali che pongono problemi per TypeTag
s. Sfortunatamente, non è così semplice a causa di https://issues.scala-lang.org/browse/SI-7686, quindi siamo costretti a usare un tag debole anche se non dovremmo averne bisogno.
Per restituire un po 'di attesa: 'implicitamente [Funz [Option, Int] <:
pedrofurla
Da https: //gist.github.com/xeno-by/6054650 Vedo che il tipo reifier non vede un tag type per B, quindi non si ottiene un tipo corretto da weakTypeOf [Funct [B, _]]. –
Ok, ora capisco qual è il problema. È di nuovo il mix tra underscore usati nelle definizioni dei parametri di tipo e altrove. Il carattere di sottolineatura in "TypeTag [B [_]]" indica un tipo esistenziale, quindi si ottiene un tag type non per 'B', ma per un wrapper esistenziale su di esso. Di conseguenza 'typeOf [Funct [B, _]]' non può usare questo tag di tipo e si arrabbia. –