简体   繁体   English

为什么scala不会将这种类型的lambda与底层类型统一起来?

[英]Why scala does not unify this type lambda with underlying type?

trait A {
  type T
  def test(t: T): Unit
}

case class B[S <: A](a: S, t : S#T) {
  def test() = a.test(t) // Error: type mismatch;
    // found   : B.this.t.type (with underlying type S#T)
    // required: B.this.a.T
}

Am I wrong to expect the above to compile? 我错误地期望上面的编译? Can my code be fixed? 我的代码可以修复吗?

Compiler has not sufficient evidence that S#T can be used as argument for test in concrete instance. 编译器没有足够的证据表明S#T可以在具体实例中用作test参数。

Consider this hypotecical example for weakened scala compiler 考虑弱化scala编译器的这个低级示例

trait A2 extends A{
  type T <: AnyRef
}

class A3 extends A2{
  override type T = Integer

  def test(t: Integer): Unit = println(t * 2)
}

So B[A2] should accept instance of A3 along with anything that is <: AnyRef while A3 needs exactly Integer for its own test implementation 所以B[A2]应该接受A3实例以及<: AnyRef任何东西,而A3需要完全Integer用于自己的test实现

You can catch concrete type in the definition of B , to make sure what type will be used 您可以在B的定义中捕获具体类型,以确保将使用哪种类型

case class B[S <: A, ST](a: S {type T = ST}, t: ST) {
  def test() = a.test(t) 
}

I could come up with encodings (removed the type parameters for simplification): 我可以提出编码(删除类型参数以简化):

scala> :paste
// Entering paste mode (ctrl-D to finish)

def test0(a: A)(t : a.T) = a.test(t) 

abstract class B{
  val a: A
  val t: a.T
  def test = a.test(t)
}

// Exiting paste mode, now interpreting.

test0: (a: A)(t: a.T)Unit
defined class B

This on the other hand didn't work with case classes arguments (nor classes' for that matter). 另一方面,这不适用于case类参数(也不适用于类)。

One of the reasons your encoding wouldn't work: 您的编码不起作用的原因之一:

scala> def test1(a: A)(t : A#T) = a.test(t) 
<console>:12: error: type mismatch;
 found   : t.type (with underlying type A#T)
 required: a.T
       def test1(a: A)(t : A#T) = a.test(t)

The important part is required: aT (versus A#T ). 重要的部分是required: aT (与A#T对比)。 The test method in A doesn't take any T, it takes T this.T , or in other words, the T belonging to one particular instance of A. A中的测试方法不带任何T,它需要T this.T ,或者换句话说,T属于A的一个特定实例。

Instead of a type projection you can use the dependent type aT : 您可以使用依赖类型aT代替类型投影:

trait A {
  type T
  def test(t: T): Unit
}

case class B[S <: A](a: S)(t : a.T) {
  def test() = a.test(t)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM