问题
Consider the following simple example involving Aux
-pattern:
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
Scastie
I don't really understand why testBaz
compiles. I expected type mismatch as well.
回答1:
It seems there is no deep reason for that.
Since when you specify type parameter explicitly both methods compile
def testBaz(baz: Baz) = Bar[baz.foo.T](baz.foo) //compiles
def testFoo(foo: Foo) = Bar[foo.T](foo) //compiles
it seems in
def testBaz(baz: Baz) = Bar(baz.foo) //compiles
//def testFoo(foo: Foo) = Bar(foo) //doesn't compile
in the first case the type baz.foo.T
is inferred while in the second case the type foo.T
is just not inferred
// found : Foo
// required: Foo.Aux[this.T]
In Scala it's always possible that some type parameter will not be inferred and you'll have to specify it explicitly.
Maybe I found a possible reason.
The code
class testFoo2(foo: Foo) {
// Bar(foo) // doesn't compile
}
doesn't compile but if you make foo
a val
class testFoo2(val foo: Foo) {
Bar(foo) // compiles
}
then it does. Probably the thing is that when foo
is a val
it's more "stable" and in such case it's "easier" to infer path-dependent type foo.T
.
So the difference between testBaz
and testFoo
can be that Baz
is a case class so foo
is a val
while in testFoo
foo
is just a method parameter and therefore less "stable".
Similarly , on contrary to
trait A[T]
def m[T](a: A[T]) = ???
m(??? : A[_]) // compiles
the code
trait A { type T }
def m[_T](a: A { type T = _T}) = ???
m(??? : A) // doesn't compile
doesn't compile but if we extract a variable
val a: A = ???
m(a) // compiles
then it does. The thing is that now a
is stable and type a.T
can be inferred.
来源:https://stackoverflow.com/questions/64672950/aux-pattern-usage-compiles-without-inferring-an-appropriate-type