I'm trying to get a minimal form of dependent types in Scala. If I have
class A[T <: Int]
val x: Int = 7
I can
val a = new A[x.type]
Now is it possible to recover x
from its singleton x.type
?
Or, if that's not possible, is it possible to associate a stable identifier with a type somehow, and then extract it?
No, you can't recover x
from x.type
because of JVM type erasure. For example, how would this be implemented?
def f[A]: A = ???
f[x.type]
At the JVM bytecode level, there's no way that f
can find value x: A
given A = x.type
because it doesn't have anything to work with: all type parameters are lost at run-time, and anyway, the x
value is not available on f
's parameter stack.
For the same reason, to get a stable-ID of a type, you'd have to reify it as a Manifest
value. But when I tried, I get a strange result,
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 !?
I'm not sure why these two type manifests are equal---they even have different toString
representations. Could this be a Scala bug? Update: According to the ScalaDoc, The type-relation operators <:< and =:= should be considered approximations only, as there are numerous aspects of type conformance which are not yet adequately represented in manifests.
To summarize, the reification of type information into run-time values doesn't happen automatically on the JVM. Scala's Manifest
is supposed to fill the gap, but I guess it doesn't work with dependent types.
To answer your second question, "associating a stable identifier to a type", one way to do it is to use type classes. Let's say I want to associate a string description to types, I can do it as follows:
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"
}
Now, to recover such tags, enter the implicit magic:
def printTag[T : Tag] {
val tag = implicitly[Tag[T]]
println("Type is described as : " + tag.desc)
}
E.g:
printTag[String] // prints "Type is described as : character string"
printTag[Double] // compile-time error: no implicit value found of type Tag[Double]
You can even generate tags as needed, using implicit functions. For instance:
implicit def liftTagToList[T : Tag] = new Tag[List[T]] {
val underlying = implicitly[Tag[T]].desc
val desc = "list of " + underlying + "s"
}
I can now do the following:
// prints "Type is described as : list of character strings"
printTag[List[String]]
and even:
// prints "Type is described as : list of list of character stringss"
printTag[List[List[String]]]
Please forgive the pluralization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With