Scala 类型参数不符合类型参数边界
Scala type arguments do not conform to type parameter bounds
我正在做一些我想概括的工作(一些行为在几个 类 中完全重复,但对于不同的具体类型 [称之为 C,见下文])有一些限制
我简化了具有类似结构的真实代码只是为了演示问题
package playground
object Conformance {
trait S
trait G
trait R {
type ST <: S
type GT <: G
def getS: ST
def getG: GT
}
trait RT[SD <: S, GD <: G] extends R {
override type ST = SD
override type GT = GD
}
final case class ConcreteS() extends S
final case class ConcreteG() extends G
final class C1 extends RT[ConcreteS, ConcreteG] {
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//some different impl
final class C2 extends RT[ConcreteS, ConcreteG]{
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//some different impl
final class C3 extends RT[ConcreteS, ConcreteG]{
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//generic impl over W
trait GeneralizationOverW[C <: RT[S, G]] {
// With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
}
class W1 extends GeneralizationOverW[C1]
class W2 extends GeneralizationOverW[C2]
class W3 extends GeneralizationOverW[C3]
}
假设 C1,C2,C3
有不同的实现(由代码生成),我试图通过 GeneralizationOverW
使用不同的 C 来概括 W
我试图阅读 Scala 规范中的 compound types,但无法弄清楚为什么会出现以下编译错误以及如何修复它:
type arguments [playground.Conformance.C1] do not conform to trait
GeneralizationOverW's type parameter bounds [C <:
playground.Conformance.RT[playground.Conformance.S,playground.Conformance.G]]
class W1 extends GeneralizationOverW[C1]
编辑:根据建议更新代码:
package playground
object Conformance {
trait S
trait SS extends S
trait G
trait R {
type ST <: S
type GT <: G
def getS: ST
def getG: GT
}
trait RT[SD <: S, GD <: G] extends R {
override type ST = SD
override type GT = GD
}
final case class ConcreteS1() extends SS
final case class ConcreteS2() extends SS
final case class ConcreteS3() extends SS
final case class ConcreteG1() extends G
final case class ConcreteG2() extends G
final case class ConcreteG3() extends G
final class C1 extends RT[ConcreteS1, ConcreteG1] {
override def getS: ConcreteS1 = ConcreteS1()
override def getG: ConcreteG1 = ConcreteG1()
}
//some different impl
final class C2 extends RT[ConcreteS2, ConcreteG2]{
override def getS: ConcreteS2 = ConcreteS2()
override def getG: ConcreteG2 = ConcreteG2()
}
//some different impl
final class C3 extends RT[ConcreteS3, ConcreteG3]{
override def getS: ConcreteS3 = ConcreteS3()
override def getG: ConcreteG3 = ConcreteG3()
}
//generic impl over W
trait GeneralizationOverW[ST <: S,GT <: G , CON <: RT[ST, GT]] {
// With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
}
class W1 extends GeneralizationOverW[ConcreteS1,ConcreteG1,C1]
class W2 extends GeneralizationOverW[ConcreteS2,ConcreteG2,C2]
class W3 extends GeneralizationOverW[ConcreteS3,ConcreteG3,C3]
}
我想现在可以了:)
我不确定这是否是您要查找的内容,但您可以尝试:
trait GeneralizationOverW[S1 <: S, G1 <: G, C <: RT[S1, G1]] {
// With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
}
class W1 extends GeneralizationOverW[ConcreteS, ConcreteG, C1]
class W2 extends GeneralizationOverW[ConcreteS, ConcreteG, C2]
class W3 extends GeneralizationOverW[ConcreteS, ConcreteG, C3]
几件事情正在发生:
trait GeneralizationOverW[C <: RT[S, G]] {
}
它期望这里传递的 C
将使用 S
和 G
而不是它的子类型精确地扩展 RT[S, G]
因为 RT
在两者中都是不变的参数。
您可以通过添加 +
使其协变
trait RT[+SD <: S, +GD <: G] {
def getS: SD
def getG: GD
}
我删除了 extends R
因为路径相关类型 ST
和 GT
在此处定义:
trait R {
type ST <: S
type GT <: G
def getS: ST
def getG: GT
}
是不变的,不能成为协变的。如果您放弃使用 R
(您的示例根本没有使用依赖于路径的类型),您可以创建一个有效代码:
object Conformance {
trait S
trait G
trait RT[+SD <: S, +GD <: G] {
def getS: SD
def getG: GD
}
final case class ConcreteS() extends S
final case class ConcreteG() extends G
final class C1 extends RT[ConcreteS, ConcreteG] {
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//some different impl
final class C2 extends RT[ConcreteS, ConcreteG]{
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//some different impl
final class C3 extends RT[ConcreteS, ConcreteG]{
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//generic impl over W
trait GeneralizationOverW[C <: RT[S, G]] {
// With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
}
class W1 extends GeneralizationOverW[C1]
class W2 extends GeneralizationOverW[C2]
class W3 extends GeneralizationOverW[C3]
}
但是,如果您确实需要这些依赖于路径的类型,您应该将硬编码的 S
和 G
替换为绑定参数,如@TomerShetah 的回答。
我正在做一些我想概括的工作(一些行为在几个 类 中完全重复,但对于不同的具体类型 [称之为 C,见下文])有一些限制
我简化了具有类似结构的真实代码只是为了演示问题
package playground
object Conformance {
trait S
trait G
trait R {
type ST <: S
type GT <: G
def getS: ST
def getG: GT
}
trait RT[SD <: S, GD <: G] extends R {
override type ST = SD
override type GT = GD
}
final case class ConcreteS() extends S
final case class ConcreteG() extends G
final class C1 extends RT[ConcreteS, ConcreteG] {
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//some different impl
final class C2 extends RT[ConcreteS, ConcreteG]{
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//some different impl
final class C3 extends RT[ConcreteS, ConcreteG]{
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//generic impl over W
trait GeneralizationOverW[C <: RT[S, G]] {
// With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
}
class W1 extends GeneralizationOverW[C1]
class W2 extends GeneralizationOverW[C2]
class W3 extends GeneralizationOverW[C3]
}
假设 C1,C2,C3
有不同的实现(由代码生成),我试图通过 GeneralizationOverW
我试图阅读 Scala 规范中的 compound types,但无法弄清楚为什么会出现以下编译错误以及如何修复它:
type arguments [playground.Conformance.C1] do not conform to trait GeneralizationOverW's type parameter bounds [C <: playground.Conformance.RT[playground.Conformance.S,playground.Conformance.G]] class W1 extends GeneralizationOverW[C1]
编辑:根据建议更新代码:
package playground
object Conformance {
trait S
trait SS extends S
trait G
trait R {
type ST <: S
type GT <: G
def getS: ST
def getG: GT
}
trait RT[SD <: S, GD <: G] extends R {
override type ST = SD
override type GT = GD
}
final case class ConcreteS1() extends SS
final case class ConcreteS2() extends SS
final case class ConcreteS3() extends SS
final case class ConcreteG1() extends G
final case class ConcreteG2() extends G
final case class ConcreteG3() extends G
final class C1 extends RT[ConcreteS1, ConcreteG1] {
override def getS: ConcreteS1 = ConcreteS1()
override def getG: ConcreteG1 = ConcreteG1()
}
//some different impl
final class C2 extends RT[ConcreteS2, ConcreteG2]{
override def getS: ConcreteS2 = ConcreteS2()
override def getG: ConcreteG2 = ConcreteG2()
}
//some different impl
final class C3 extends RT[ConcreteS3, ConcreteG3]{
override def getS: ConcreteS3 = ConcreteS3()
override def getG: ConcreteG3 = ConcreteG3()
}
//generic impl over W
trait GeneralizationOverW[ST <: S,GT <: G , CON <: RT[ST, GT]] {
// With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
}
class W1 extends GeneralizationOverW[ConcreteS1,ConcreteG1,C1]
class W2 extends GeneralizationOverW[ConcreteS2,ConcreteG2,C2]
class W3 extends GeneralizationOverW[ConcreteS3,ConcreteG3,C3]
}
我想现在可以了:)
我不确定这是否是您要查找的内容,但您可以尝试:
trait GeneralizationOverW[S1 <: S, G1 <: G, C <: RT[S1, G1]] {
// With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
}
class W1 extends GeneralizationOverW[ConcreteS, ConcreteG, C1]
class W2 extends GeneralizationOverW[ConcreteS, ConcreteG, C2]
class W3 extends GeneralizationOverW[ConcreteS, ConcreteG, C3]
几件事情正在发生:
trait GeneralizationOverW[C <: RT[S, G]] {
}
它期望这里传递的 C
将使用 S
和 G
而不是它的子类型精确地扩展 RT[S, G]
因为 RT
在两者中都是不变的参数。
您可以通过添加 +
trait RT[+SD <: S, +GD <: G] {
def getS: SD
def getG: GD
}
我删除了 extends R
因为路径相关类型 ST
和 GT
在此处定义:
trait R {
type ST <: S
type GT <: G
def getS: ST
def getG: GT
}
是不变的,不能成为协变的。如果您放弃使用 R
(您的示例根本没有使用依赖于路径的类型),您可以创建一个有效代码:
object Conformance {
trait S
trait G
trait RT[+SD <: S, +GD <: G] {
def getS: SD
def getG: GD
}
final case class ConcreteS() extends S
final case class ConcreteG() extends G
final class C1 extends RT[ConcreteS, ConcreteG] {
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//some different impl
final class C2 extends RT[ConcreteS, ConcreteG]{
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//some different impl
final class C3 extends RT[ConcreteS, ConcreteG]{
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//generic impl over W
trait GeneralizationOverW[C <: RT[S, G]] {
// With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
}
class W1 extends GeneralizationOverW[C1]
class W2 extends GeneralizationOverW[C2]
class W3 extends GeneralizationOverW[C3]
}
但是,如果您确实需要这些依赖于路径的类型,您应该将硬编码的 S
和 G
替换为绑定参数,如@TomerShetah 的回答。