gpt4 book ai didi

scala - 避免 Scala 中的冗余泛型参数

转载 作者:行者123 更新时间:2023-12-04 08:32:46 25 4
gpt4 key购买 nike

所以这是 this Java question 的一个相当直接的端口到斯卡拉

我们有一堆采用通用参数的特征,如下所示:

 trait Ident { }

trait Container[I <: Ident] {
def foo(id: I): String
}

trait Entity[C <: Container[I], I <: Ident] {
def container: C
def foo(id: I) = container.foo(id)
}

这可行,但有点笨拙,因为我们必须在定义实体的子类时提供 Ident 的类型和 Container 的类型。实际上,仅 Container 的类型本身就足够了类型信息:
class MyIdent extends Ident { }
class MyContainer extends Container[MyIdent] { }
class MyEntity extends Entity[MyContainer,MyIdent] { }
// ^^^^^^^ shouldn't really be necessary

使用存在类型可以避免 Entity 需要两个参数......但当然你以后不能引用它。
trait Entity[C <: Container[I] forSome { type I <: Ident }] {
def container: C
def foo(id: I) = container.foo(id)
// ^^^ complains it has no idea what 'I' is here
}

同样将事物转换为使用成员类型也不起作用......
trait Ident { }

trait Container {
type I <: Ident
def foo(id: I): String
}

trait Entity {
type C <: Container
def container: C
def foo(id: C#I) = container.foo(id)
// ^^ type mismatch
}

那么有谁知道 Scala 中是否有一个优雅的解决方案来解决这个问题?

最佳答案

更新 给定 this answer我不确定这是否应该被视为错误

你打了 SI-4377 ;如果您提供明确的 type ascriptions你会得到一个错误,我猜它只是暴露了类型投影是使用存在实现的:

trait Ident { }

trait Container {
type I <: Ident
def foo(id: I): String
}

trait Entity {

type C <: Container
def container: C
def foo(id: C#I): String = (container: C).foo(id: C#I)
// you will get something like: type mismatch;
// [error] found : Entity.this.C#I
// [error] required: _3.I where val _3: Entity.this.C
// as I said above, see https://issues.scala-lang.org/browse/SI-4377
}

毫不夸张地说,这(错误?)使使用类型成员的泛型编程成为一场噩梦。

不过有一个技巧,其中包括将值转换为手工制作的自引用类型别名:

case object Container {

type is[C <: Container] = C with Container {

type I = C#I
// same for all other type members, if any
}

def is[C <: Container](c: C): is[C] = c.asInstanceOf[is[C]]
}

现在使用它和 Entity编译:

trait Entity {

type C <: Container
def container: C
def foo(id: C#I): String = Container.is(container).foo(id)
// compiles!
}

这当然是危险的,根据经验,只有在 C 时才是安全的。并且它的所有类型成员在使用时都绑定(bind)到非抽象类型;请注意,情况并非总是如此,因为 Scala 允许您保留“未定义”类型成员:

case object funnyContainer extends Container {

// I'm forced to implement `foo`, but *not* the `C` type member
def foo(id: I): String = "hi scalac!"
}

关于scala - 避免 Scala 中的冗余泛型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40511122/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com