我可以用一种简单的方法在 Scala 中获得一个未包装的单例类型吗?
Can I obtain an unwrapped singleton type in Scala with a simple method?
在 Scala 中,在围绕 Miles Sabin 的无形库的讨论中,我看到了这样的代码:
def sing[T <: String](t: T): Option[t.type] = Some(t)
像这样的地方:
val name = sing("name")
类型为 Option[Constant(name).type]
。我想“为什么要用 Option
包装它”?但是如果我试试这个:
def sing2[T <: String](t: T): t.type = t
val name2 = sing2("name")
然后 name2
的类型为 String
,而我本以为它是 Constant(name).type
。我错过了什么?有没有不涉及包装单例类型的解决方法?
似乎 scalac 向上转换类型。我不知道,如果它是设计使然还是错误。如果强制输入:
def sing2[T <: String](t: T): t.type = t
val n = "name"
val name2: n.type = sing2(n)
// name2: n.type = name
您似乎无法构造 String(<string-literal>)
类型的值,只能使用限定名称:
scala> sing2("name")
res0: String = name
scala> val n = "name"
n: String = name
scala> sing2(n)
res1: n.type = name
但你不能说
val name2: n.type = sing("name")
因为
<console>:12: error: type mismatch;
found : String("name")
required: n.type
也没有
name2: "name".type = sing2("name")
// or
name2: "name" = sing2("name")
这是 scalac 的一个已知怪癖。
单例类型是内部编译器,它们已经存在很长时间了,但从未打算向用户公开。因此,无法保证它们的 "API",事实上 scalac 会尽可能地使它们 "disappear"。
这几乎就是为什么 Miles 必须在需要时使用 Witness 类型来包装单例类型(例如可扩展记录键)的原因。
显然,将它们包装在一个容器中会导致编译器保留实际类型,这就是 Option
的情况。
正如 Oleg 在另一个答案中提到的,正在努力使单例类型正式成为语言的一部分:http://docs.scala-lang.org/sips/pending/42.type.html
在 Scala 中,在围绕 Miles Sabin 的无形库的讨论中,我看到了这样的代码:
def sing[T <: String](t: T): Option[t.type] = Some(t)
像这样的地方:
val name = sing("name")
类型为 Option[Constant(name).type]
。我想“为什么要用 Option
包装它”?但是如果我试试这个:
def sing2[T <: String](t: T): t.type = t
val name2 = sing2("name")
然后 name2
的类型为 String
,而我本以为它是 Constant(name).type
。我错过了什么?有没有不涉及包装单例类型的解决方法?
似乎 scalac 向上转换类型。我不知道,如果它是设计使然还是错误。如果强制输入:
def sing2[T <: String](t: T): t.type = t
val n = "name"
val name2: n.type = sing2(n)
// name2: n.type = name
您似乎无法构造 String(<string-literal>)
类型的值,只能使用限定名称:
scala> sing2("name")
res0: String = name
scala> val n = "name"
n: String = name
scala> sing2(n)
res1: n.type = name
但你不能说
val name2: n.type = sing("name")
因为
<console>:12: error: type mismatch;
found : String("name")
required: n.type
也没有
name2: "name".type = sing2("name")
// or
name2: "name" = sing2("name")
这是 scalac 的一个已知怪癖。
单例类型是内部编译器,它们已经存在很长时间了,但从未打算向用户公开。因此,无法保证它们的 "API",事实上 scalac 会尽可能地使它们 "disappear"。
这几乎就是为什么 Miles 必须在需要时使用 Witness 类型来包装单例类型(例如可扩展记录键)的原因。
显然,将它们包装在一个容器中会导致编译器保留实际类型,这就是 Option
的情况。
正如 Oleg 在另一个答案中提到的,正在努力使单例类型正式成为语言的一部分:http://docs.scala-lang.org/sips/pending/42.type.html