Scala——继承树中的多个 F 有界类型
Scala -- multiple F-bounded types in inheritance tree
我在 Scala 中有一个通用的 F 有界特征。让我编写 return 相同底层实现类型的方法,超级!但是现在假设子特征 also 定义了需要 F 边界的方法。 Scala 将无意义的编译错误发回给我:
package sandbox
import sandbox.ComplexImpl.AnyComplexImpl
import scala.language.existentials
trait FBounded[IMPL <: FBounded[IMPL]] { self: IMPL =>
def foo: IMPL
}
trait FBoundedUser[F <: FBounded[F]] {
def bar(value: F): F = value.foo
}
trait SimpleImpl extends FBounded[SimpleImpl] {
override def foo: SimpleImpl = this
}
object SimpleUser extends FBoundedUser[SimpleImpl]
// A-OK so far...
trait ComplexImpl[IMPL <: ComplexImpl[IMPL]] extends FBounded[IMPL] { self: IMPL =>
def baz: IMPL
}
object ComplexImpl {
type AnyComplexImpl = ComplexImpl[T] forSome { type T <: ComplexImpl[T] }
}
object ComplexUser1 extends FBoundedUser[ComplexImpl[_]]
object ComplexUser2 extends FBoundedUser[AnyComplexImpl]
尝试使用 ComplexUser1
或 ComplexUser2
之一进行编译会导致:
Error:(32, 29) type arguments [sandbox.ComplexImpl.AnyComplexImpl] do not conform to trait
FBoundedUser's type parameter bounds [F <: sandbox.FBounded[F]]
这对我来说没有意义。 AnyComplexImpl
绝对实现 FBounded
。我错过了什么,还是类型检查器让我失望了?
编辑:
class Concrete() extends ComplexImpl[Concrete] {
override def baz: Concrete = this
override def foo: Concrete = this
}
object ComplexUser3 extends FBoundedUser[Concrete]
编译正常。那么为什么通用版本不会呢?
约束需要 AnyComplexImpl
来实现 FBounded[AnyComplexImpl]
,但它不需要,而不仅仅是 FBounded[T] forSome { type T <: ComplexImpl[T] }
。
如果您使 FBounded
和 ComplexImpl
协变,它就会起作用。编译器的原因是:
AnyComplexImpl
是任何 ComplexImpl[T]
的超类型,其中 T <: ComplexImpl[T]
;
所以FBounded[T] forSome { type T <: ComplexImpl[T] }
是FBounded[AnyComplexImpl]
的子类型;
所以AnyComplexImpl
是FBounded[AnyComplexImpl]
的子类型。
但我怀疑尝试混合 F 有界类型和存在性可能会导致其他问题。 ComplexUser1
和 ComplexUser2
不编译的原因恰恰是它们不是通用的。考虑改用实际的通用版本:
def complexUser4[T <: ComplexImpl[T]] = new FBoundedUser[T] {}
我在 Scala 中有一个通用的 F 有界特征。让我编写 return 相同底层实现类型的方法,超级!但是现在假设子特征 also 定义了需要 F 边界的方法。 Scala 将无意义的编译错误发回给我:
package sandbox
import sandbox.ComplexImpl.AnyComplexImpl
import scala.language.existentials
trait FBounded[IMPL <: FBounded[IMPL]] { self: IMPL =>
def foo: IMPL
}
trait FBoundedUser[F <: FBounded[F]] {
def bar(value: F): F = value.foo
}
trait SimpleImpl extends FBounded[SimpleImpl] {
override def foo: SimpleImpl = this
}
object SimpleUser extends FBoundedUser[SimpleImpl]
// A-OK so far...
trait ComplexImpl[IMPL <: ComplexImpl[IMPL]] extends FBounded[IMPL] { self: IMPL =>
def baz: IMPL
}
object ComplexImpl {
type AnyComplexImpl = ComplexImpl[T] forSome { type T <: ComplexImpl[T] }
}
object ComplexUser1 extends FBoundedUser[ComplexImpl[_]]
object ComplexUser2 extends FBoundedUser[AnyComplexImpl]
尝试使用 ComplexUser1
或 ComplexUser2
之一进行编译会导致:
Error:(32, 29) type arguments [sandbox.ComplexImpl.AnyComplexImpl] do not conform to trait
FBoundedUser's type parameter bounds [F <: sandbox.FBounded[F]]
这对我来说没有意义。 AnyComplexImpl
绝对实现 FBounded
。我错过了什么,还是类型检查器让我失望了?
编辑:
class Concrete() extends ComplexImpl[Concrete] {
override def baz: Concrete = this
override def foo: Concrete = this
}
object ComplexUser3 extends FBoundedUser[Concrete]
编译正常。那么为什么通用版本不会呢?
约束需要 AnyComplexImpl
来实现 FBounded[AnyComplexImpl]
,但它不需要,而不仅仅是 FBounded[T] forSome { type T <: ComplexImpl[T] }
。
如果您使 FBounded
和 ComplexImpl
协变,它就会起作用。编译器的原因是:
AnyComplexImpl
是任何ComplexImpl[T]
的超类型,其中T <: ComplexImpl[T]
;所以
FBounded[T] forSome { type T <: ComplexImpl[T] }
是FBounded[AnyComplexImpl]
的子类型;所以
AnyComplexImpl
是FBounded[AnyComplexImpl]
的子类型。
但我怀疑尝试混合 F 有界类型和存在性可能会导致其他问题。 ComplexUser1
和 ComplexUser2
不编译的原因恰恰是它们不是通用的。考虑改用实际的通用版本:
def complexUser4[T <: ComplexImpl[T]] = new FBoundedUser[T] {}