我是否在这里遗漏了有关 Scala 中的列表和元组的内容?
我认为 Odersky 试图展示的主要观点是每个元组元素都可以包含自己的单独类型,这允许使用多种不同的类型。 List 无法做到的事情,因为列表是同质的,这意味着如果您想要 List[Int],则该列表的所有元素都必须是 Int 值。
如果查看您创建的列表的类型,您会看到编译器推断出List[Any],这是所有 Scala 类型的通用超类型。这意味着如果你想对列表中的一个元素做一些具体的事情,即它是Int 类型的头元素,你不能因为编译器知道那个元素是它的类型@ 987654327@,您需要了解如何提取底层的“具体”类型:
scala> val oneTwoThreee = List(1,2,"Third Element")
oneTwoThreee: List[Any] = List(1, 2, Third Element)
在使用Tuple3[Int, Int, String] 时,实际上“保留”了具体类型:
scala> val tup = (1, 2, "Third Element")
tup: (Int, Int, String) = (1,2,Third Element)
现在,如果我们想提取 Int 值之一并将它们加 1,我们可以:
scala> tup.copy(tup._1 + 1)
res1: (Int, Int, String) = (2,2,Third Element)
如果我们尝试对 List[Any] 做同样的事情,编译器会理所当然地抱怨:
scala> oneTwoThreee.head + 1
<console>:13: error: type mismatch;
found : Int(1)
required: String
oneTwoThreee.head + 1
^
这个错误有点误导,但这是因为head实际上是Any类型。
使用shapeless 和它的HList 数据类型可以更高级地使用异构列表:
import shapeless._
object Tests {
def main(args: Array[String]): Unit = {
val hList = 1 :: 2 :: "Third" :: HNil
println(hList.head + 1)
}
}
产量:
2