Reputation: 3390
val s1: ({type T <: String})#T = "some string" // failed
val s2: ({type T = String})#T = "some string" // compiled
Why first line failed to compile? Why T
can't be a string there?
Edit:
Simplified case without lambdas.(Not sure if that is exactly the same from type system perspective)
trait K {
type T <: String
val s1:T = "some string" // failed
}
Edit 2 :
one more case
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
Upvotes: 0
Views: 92
Reputation: 51658
k.T
is a path-dependent type. It can be different for every instance k
of 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 = ???
}
Upvotes: 2
Reputation: 170735
The issue is not that T
can't be a string, but that it can potentially be something else, to which a string can't be assigned (e.g. Null
or Nothing
).
Upvotes: 2
Reputation: 51271
I believe it has to do with the variance relationship to the return (result) type.
Notice that T
is accepted as an input String
...
def s3[T <: String](s:T) = "some string" // T as input
s3("blah") //input T = String
... but not as an output String
.
def s3[T <: String](s:T):T = "some string" // fails to compile
// ^^^
But reverse the T
-to-String
relationship and this works ...
def s3[T >: String](s:T):T = "some string" // T as input and output
s3("blah")
... and so does this.
val s1: ({type T >: String})#T = "some string" // good
Upvotes: 4