In Scala, in a discussion around Miles Sabin's shapeless library, I've seen code like this:
def sing[T <: String](t: T): Option[t.type] = Some(t)
where something like this:
val name = sing("name")
has type Option[Constant(name).type]
. I thought “why wrap it in an Option
”? But if I try this:
def sing2[T <: String](t: T): t.type = t
val name2 = sing2("name")
then name2
has type String
, whereas I would have expected it to be Constant(name).type
. What am I missing? Is there a workaround that does not involve wrapping the singleton type?
This is a known quirk of scalac.
Singleton types are a compiler internal and they've been there for a long time, but they've never been meant to be exposed to the users. So, there's no guarantee about their "API" and as a matter of fact scalac tries to make them "disappear" whenever it can.
This is pretty much the reason why Miles had to use a Witness type to wrap singleton types whenever needed (e.g. extensible record keys).
Apparently, wrapping them in a container causes the compiler to retain the actual type, and this is what happens with Option
.
As Oleg mentioned in the other answer, there's an ongoing effort to make singleton type officially part of the language: http://docs.scala-lang.org/sips/pending/42.type.html