Scalaでは、シングルトンタイプが参照する「ヴァル」を取得することは可能ですか?
-
27-10-2019 - |
質問
Scalaで依存型の最小限の形を取得しようとしています。私が持っているなら
class A[T <: Int]
val x: Int = 7
できます
val a = new A[x.type]
これは回復することができますか? x
シングルトンから x.type
?
または、それが不可能な場合、安定した識別子を何らかの形でタイプに関連付けて、それを抽出することは可能ですか?
解決
いいえ、回復することはできません x
から x.type
JVMタイプの消去のため。たとえば、これはどのように実装されますか?
def f[A]: A = ???
f[x.type]
JVMバイトコードレベルでは、 f
価値を見つけることができます x: A
与えられた A = x.type
それは作業するものが何もないので:すべてのタイプパラメーターは実行時に失われ、とにかく、 x
値は利用できません f
'のパラメータースタック。
同じ理由で、タイプの安定したIDを取得するには、それを具体化する必要があります。 Manifest
価値。しかし、私が試したとき、私は奇妙な結果を得る、
def f[A : Manifest] = implicitly[Manifest[A]]
val x = "hi"
val y = "ho"
println(f[x.type]) // hi.type
println(f[y.type]) // ho.type
f[x.type] == f[y.type] // true !?
これらの2つのタイプのマニフェストが等しい理由はわかりません---彼らは違うことさえあります toString
表現。これはスカラのバグでしょうか? アップデート: : による スカラドック, タイプ関連演算子
要約すると、JVMでタイプ情報を実行時値に具体化することは自動的に発生しません。 Scala's Manifest
ギャップを埋めることになっていますが、従属タイプでは機能しないと思います。
他のヒント
2番目の質問「安定した識別子をタイプに関連付ける」に答えるために、それを行う1つの方法は、タイプクラスを使用することです。文字列の説明をタイプに関連付けたいとしましょう。次のように行うことができます。
trait Tag[A] {
val desc : String
}
implicit object StringTag extends Tag[String] {
val desc = "character string"
}
implicit object IntTag extends Tag[Int] {
val desc = "32-bit integer"
}
ここで、そのようなタグを回復するには、暗黙の魔法を入力してください。
def printTag[T : Tag] {
val tag = implicitly[Tag[T]]
println("Type is described as : " + tag.desc)
}
例えば:
printTag[String] // prints "Type is described as : character string"
printTag[Double] // compile-time error: no implicit value found of type Tag[Double]
暗黙の関数を使用して、必要に応じてタグを生成することもできます。例えば:
implicit def liftTagToList[T : Tag] = new Tag[List[T]] {
val underlying = implicitly[Tag[T]].desc
val desc = "list of " + underlying + "s"
}
これで次のことができます。
// prints "Type is described as : list of character strings"
printTag[List[String]]
そしてさらに:
// prints "Type is described as : list of list of character stringss"
printTag[List[List[String]]]
複数形を許してください。