为什么 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
}
我期望上面的编译是错误的吗?我的代码可以修复吗?
我可以想出编码(为了简化删除了类型参数):
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
另一方面,这不适用于 case 类 参数(也不适用于 类')。
您的编码不起作用的原因之一:
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
,或者换句话说,属于 A.
的一个特定实例的 T
编译器没有足够的证据表明 S#T
可以在具体实例中用作 test
的参数。
考虑这个弱化 scala 编译器的 hypotecical 示例
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
作为它自己的 test
实施
您可以在 B
的定义中捕获具体类型,以确保将使用什么类型
case class B[S <: A, ST](a: S {type T = ST}, t: ST) {
def test() = a.test(t)
}
您可以使用依赖类型 a.T
:
而不是类型投影
trait A {
type T
def test(t: T): Unit
}
case class B[S <: A](a: S)(t : a.T) {
def test() = a.test(t)
}
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
}
我期望上面的编译是错误的吗?我的代码可以修复吗?
我可以想出编码(为了简化删除了类型参数):
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
另一方面,这不适用于 case 类 参数(也不适用于 类')。
您的编码不起作用的原因之一:
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
,或者换句话说,属于 A.
编译器没有足够的证据表明 S#T
可以在具体实例中用作 test
的参数。
考虑这个弱化 scala 编译器的 hypotecical 示例
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
作为它自己的 test
实施
您可以在 B
的定义中捕获具体类型,以确保将使用什么类型
case class B[S <: A, ST](a: S {type T = ST}, t: ST) {
def test() = a.test(t)
}
您可以使用依赖类型 a.T
:
trait A {
type T
def test(t: T): Unit
}
case class B[S <: A](a: S)(t : a.T) {
def test() = a.test(t)
}