Aux-pattern 用法在不推断适当类型的情况下进行编译
Aux-pattern usage compiles without inferring an appropriate type
考虑以下涉及 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
时,它更“稳定”,在这种情况下,推断 path-dependent 类型 foo.T
.
更“容易”
所以 testBaz
和 testFoo
之间的区别可能是 Baz
是一个案例 class 所以 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
可以被推断出来。
考虑以下涉及 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
时,它更“稳定”,在这种情况下,推断 path-dependent 类型 foo.T
.
所以 testBaz
和 testFoo
之间的区别可能是 Baz
是一个案例 class 所以 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
可以被推断出来。