抽象类型成员的类型推断

时间:2018-10-07 05:22:56

标签: scala generics

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

3 个答案:

答案 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
//                      ^^^

但是颠倒TString的关系,就可以了...

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.Tpath-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 = ???
}