::[Int] 与 List[Int] 相同吗?

  • 本文关键字:Int List list scala cons
  • 更新时间 :
  • 英文 :

scala> val w = new ::[Int](4,Nil)
w: scala.collection.immutable.::[Int] = List(4)
scala> val x = List[Int](4)
x: List[Int] = List(4)

这两种表达有什么区别?::[Int](4)List[int]的实例,因为::[Int](4)List[Int](4)List(4)

::[T]是代数数据类型List[T]构造函数之一。另一个是Nil。考虑以下List的归纳定义

sealed trait List[+T]
case object Nil extends List[Nothing] 
case class ::[T](head: T, tail: List[T]) extends List[T]

::可能看起来有点奇怪,因为它纯粹是象征性名称,在其他语言中,它有时被称为Cons.构造函数是制作类型List[T]的方法,这里有一些

Nil
::(1, Nil)
::(2, ::(1, Nil))
::(42, ::(2, ::(1, Nil)))

这些值具有归纳性质,具有显着的性质,即每当我们有一个值时,我们总是知道如何构造以下值。换句话说,归纳值意味着归纳值。例如,两者

::(2, ::(1, Nil))

::(51, ::(1, Nil))

是构造函数::[Int]的力量::(1, Nil)的含义。

::[Int]List[Int]一样吗?

因为 Scala 使用继承形式实现代数数据类型,所以确实存在is-a-subtype-of关系

implicitly[::[Int] <:< List[Int]] // ok!

虽然不存在平等关系

implicitly[::[Int] =:= List[Int]] // error!

然而,在我看来,这些子类型关系不是代数数据类型的重点,在 Scala 中是偶然的。相反,构造函数::[T]与其构造的值的类型List[T]之间的关系更类似于函数类型之间的关系。

new ::[Int](4, Nil)List[Int](4)一样吗?

它们的计算结果都相同,例如以下传递

assert(new ::[Int](4, Nil) == List[Int](4))

然而,我们得出这个值的方式是完全不同的。在前一种情况下,我们直接使用List[Int]ADT 的构造函数,而在后一种情况下,我们实际上是在trait List[T]伴随对象上调用apply方法

List.apply[Int](4)

其中apply定义为

def apply[A](xs: A*): List[A] = xs.toList

现在在实践中,我们很少需要考虑这些事情。通常我们只是写一些类似的东西

List(4, 2, 42)

并完成它。"低级"构造函数::有时会在模式匹配期间显示其面孔,这是一种解构ADT 的方法,例如,这里是递归实现,它获取列表中元素的总和

def sum(l: List[Int]): Int = {
l match {
case Nil => 0
case head :: tail => head + sum(tail)
}
}
sum(List(1, 2, 42)) 
// res1: Int = 45

abstract class List是密封的,所以它只由类::[+A]object Nil扩展。

这意味着,为了符合type List[+A],一个对象必须是type ::[X]的,其中X符合A,或者Nil符合List[Nothing]

type List[Int]很可能是Nil的,因为List[Nothing]符合List[Int]。另一方面,您不能将Nil赋值type ::[Int],因为它不是::[_]

TL;博士: 每个::[_]都是一个List[_],但不是每个List[_]都是::[_]

相关内容

  • 没有找到相关文章

最新更新