gpt4 book ai didi

scala - 将泛型类型放入 Scala 列表中

转载 作者:行者123 更新时间:2023-12-05 01:46:57 25 4
gpt4 key购买 nike

我正在尝试创建一个通用类型并将它们放入一个列表中。这是我的代码。

class A
class B extends A
class C extends B

class G[T <: B] {
def x(t: T) = {}
}

val g1 = new G[B]
val g2 = new G[C]

//val list1: List[G[B]] = List(g1, g2) -- this would not compile.
val list: List[G[_ <: B]] = List(g1, g2)
list.head.x()//now what ?

我原以为 x 的类型是 B 但编译器却提示

_$1 where type _$1 <: com.example.cake.modules.robotics.B
list.head.x(new B)

快速谷歌搜索问题指向我的通配符 (_ <: B)。但是不确定如何修复。

最佳答案

shapeless 的可能方法

由于以下部分所述的原因,当您将元素放入列表中时,您会丢失关于 g1 的精确类型的信息。和 g2 . shapeless 不是这种情况。 HList:

> import shapeless._

> val list = g1 :: g2 :: HNil
list: G[B] :: G[C] :: HNil = ::(cmd7$G@3a94d716, ::(cmd7$G@64992713, HNil))

> list.head.x(new B)
// successful

解释为什么编译器拒绝代码

编译器所说的实际上是完全合理的(尽管有些晦涩):请注意 g2的类型是 G[C]及其 x成员(member)只接受 C (或任何子类型)作为参数。

事实上:

scala> :type g2
G[C]

scala> g2.x(new C)

scala> g2.x(new B)
<console>:16: error: type mismatch;
found : B
required: C
g2.x(new B)
^

当您同时添加 g1 时和 g2你失去了两者的精确类型,最终,对于元素类型,无论你得到什么元素,都需要安全的东西。 List[G[_ <: B]]意味着对于列表的每个元素,TG[T]需要是 T <: B而且这是您从列表中取出的元素的唯一保证。所以,最后,你得到了什么 list.headG[T <: B]因此 T可以是 B 的任何子类型(这是一个无限集)因此,如果它是,例如,T = C然后x只接受属于 C 子类型的值作为其 t争论。这使得实际上不可能为 t 提供值。作为T可能只是 Nothing (底部有人居住的类型,没有任何值(value))。

事实上,如果让 scalac 推断出 list 的类型,你得到:

scala> val list = List(g1, g2)
list: List[G[_ >: C <: B]] = List(G@379619aa, G@cac736f)

上面写着 TG[T]必须是 B 的子类型和 C 的父类(super class)型, 这将下限设为 T从而允许调用 list.head.x(new C)但不是 list.head.x(new B) :

scala> list.head.x(new B)
<console>:18: error: type mismatch;
found : B
required: _2 where type _2 >: C <: B
list.head.x(new B)

重要的是要注意,如果不使用 head,则会发生完全相同的情况。你捕获了列表的第二个元素list(1) .

为了弄清楚这里应该做什么,我们可能需要更多地了解您想要实现的目标,因为没有简单的“修复”。

关于scala - 将泛型类型放入 Scala 列表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33165884/

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