これは、型パラメーターの定義などで使用されるアンダースコアの混同です。のアンダースコアはTypeTag[B[_]]
存在型を意味するため、 ではなく、その上に存在するラッパーのタグを取得しますB
。これは、手動の後処理なしではほとんど役に立ちません。
したがってtypeOf[Funct[B, _]]
、raw のタグが必要なB
場合は、ラッパーのタグを使用できず、動揺します。動揺するということは、タグをスコープ内でスプライスすることを拒否し、コンパイルエラーで失敗することを意味します。代わりに使用weakTypeOf
すると、それは成功しますが、スプライスできなかったすべてのスタブが生成され、結果がサブタイプ チェックに役に立たなくなります。
この場合、Scala には種類のポリモーフィズムがないため、 でrawB
を参照する方法がないという意味で、本当に Scala の限界に達しているように見えます。DOTWeakTypeTag[B]
のようなものがこの不都合から私たちを救ってくれることを願っていますが、それまでの間、この回避策を使用できます (きれいではありませんが、私はより簡単なアプローチを思い付くことができませんでした)。
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
の署名にを使用していることに気付くでしょう。結局のところ、未解決の型パラメーターや s に問題を引き起こすローカル クラスを含まないという意味で、行儀の良い型であるan に対して foo を呼び出します。残念ながら、 https://issues.scala-lang.org/browse/SI-7686のせいでそれほど単純ではありません。そのため、必要のないはずの弱いタグを使用せざるを得ません。foo
TypeTag
Option
TypeTag