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

时间:2016-12-05 20:27:13

标签: scala existential-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
}

我错误地期望以上编译?我的代码可以修复吗?

3 个答案:

答案 0 :(得分:8)

编译器没有足够的证据证明S#T可以在具体实例中用作test的参数。

考虑弱化的scala编译器

的这个荒谬的例子
trait A2 extends A{
  type T <: AnyRef
}

class A3 extends A2{
  override type T = Integer

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

所以B[A2]应该接受A3的实例以及<: AnyRef的任何内容,A3需要Integer的{​​{1}}实现test

您可以在B的定义中捕捉具体类型,以确定将使用的类型

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

答案 1 :(得分:2)

我可以提出编码(删除类型参数以简化):

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

另一方面,这并不适用于案例类参数(也不是类和#39;)。

您的编码不起作用的原因之一:

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)

重要的部分是required: a.T(与A#T对比)。 A中的测试方法不包含任何T,它需要T this.T,或者换句话说,T属于A的一个特定实例。

答案 2 :(得分:1)

您可以使用从属类型_handleBeforeInput = () => { const currentContent = this.state.editorState.getCurrentContent(); const currentContentLength = currentContent.getPlainText('').length if (currentContentLength > MAX_LENGTH - 1) { console.log('you can type max ten characters'); return 'handled'; } }

,而不是类型投影
a.T