如何解决辅助模式用法在不推断适当类型的情况下进行编译
考虑以下涉及Aux
模式的简单示例:
sealed trait AdtBase
abstract case class Foo(){
type T <: AdtBase
}
object Foo{
type Aux[TT] = Foo { type T = TT }
}
abstract case class Bar(){
type T <: AdtBase
val foo: Foo.Aux[T]
}
object Bar {
type Aux[TT] = Bar { type T = TT }
def apply[TT <: AdtBase](f: Foo.Aux[TT]): Bar = new Bar() {
override type T = TT
override val foo: Foo.Aux[T] = f
}
}
case class Baz(foo: Foo)
def testBaz(baz: Baz) = Bar(baz.foo) //Compiles fine
def testFoo(foo: Foo) = Bar(foo) //Error: Type mismatch
我不太了解testBaz
为何编译。我也期望类型不匹配。
解决方法
似乎没有深层原因。
自从您明确指定类型参数以来,这两种方法都可以编译
def testBaz(baz: Baz) = Bar[baz.foo.T](baz.foo) //compiles
def testFoo(foo: Foo) = Bar[foo.T](foo) //compiles
似乎在
def testBaz(baz: Baz) = Bar(baz.foo) //compiles
//def testFoo(foo: Foo) = Bar(foo) //doesn't compile
在第一种情况下,类型baz.foo.T
会被推断,而在第二种情况下,类型foo.T
不会被推断
// found : Foo
// required: Foo.Aux[this.T]
在Scala中,总是有可能无法推断出某些类型参数,而您必须显式地指定它。
也许我找到了可能的原因。
代码
class testFoo2(foo: Foo) {
// Bar(foo) // doesn't compile
}
不会编译,但是如果您将foo
设为val
class testFoo2(val foo: Foo) {
Bar(foo) // compiles
}
然后就可以了。可能的事情是,当foo
是val
时,它更加“稳定”,在这种情况下,推断路径依赖类型foo.T
的过程更加“容易”。
因此testBaz
和testFoo
之间的区别可能是Baz
是一个案例类,因此foo
是val
,而在testFoo
foo
只是一个方法参数,因此不太“稳定”。
类似地,与
相反trait A[T]
def m[T](a: A[T]) = ???
m(??? : A[_]) // compiles
代码
trait A { type T }
def m[_T](a: A { type T = _T}) = ???
m(??? : A) // doesn't compile
不会编译,但是如果我们提取一个变量
val a: A = ???
m(a) // compiles
然后就可以了。事实是,现在a
稳定了,可以推断出类型a.T
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。