[英]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.