val s1: ({type T <: String})#T = "some string" // failed
val s2: ({type T = String})#T = "some string" // compiled
为什么第一行编译失败?为什么T
不能在此处输入字符串?
编辑:
没有lambda的简化大小写。(从类型系统角度来看,不确定是否完全相同)
trait K {
type T <: String
val s1:T = "some string" // failed
}
编辑2:
还有一种情况
type K = {type T <: String}
val s1:K#T = "some string" // failed
def test(in: K#T):K#T = in // can be used as output type as well
答案 0 :(得分:4)
我认为这与返回(结果)类型的方差关系有关。
请注意,T
被接受为输入String
...
def s3[T <: String](s:T) = "some string" // T as input
s3("blah") //input T = String
...但不作为输出String
。
def s3[T <: String](s:T):T = "some string" // fails to compile
// ^^^
但是颠倒T
与String
的关系,就可以了...
def s3[T >: String](s:T):T = "some string" // T as input and output
s3("blah")
...等等。
val s1: ({type T >: String})#T = "some string" // good
答案 1 :(得分:2)
问题不是T
不能是字符串,而可能是其他不能分配字符串的东西(例如Null
或{{1} }。
答案 2 :(得分:2)
k.T
是path-dependent type。对于k
的每个实例K
,它可能是不同的。
trait K {
type T <: String
val s1: T /*= "some string"*/
}
object K1 extends K {
override type T = Null
override val s1 = null
}
object K2 extends K {
override type T = Nothing
override val s1 = ???
}
object K3 extends K {
override type T = String with Int
override val s1 = ???
}
object K4 extends K {
override type T = shapeless.Witness.`"some other string"`.T
override val s1 = "some other string"
}
object K5 extends K {
// K5.T is abstract
override val s1 = ???
}
object K6 extends K {
// K6.T is abstract but different from K5.T
override val s1 = ???
}