Scala通用列表实现

时间:2013-10-02 15:13:56

标签: scala

在遵循Scala课程我的Odersky课程时,我实现了下面的List示例:

trait List[T] {
    def isEmpty : Boolean
    def head : T
    def tail : List[T]

    override def toString() = if(this.isEmpty) "" else  "{" + head + tail + "}"
}

class Cons[T](val head: T, val tail: List[T]) extends List[T] {
    def isEmpty : Boolean = false
}

class Nil[T] extends List[T] {
    def isEmpty : Boolean = true
    def head : Nothing  = throw new NoSuchElementException("Nil.head")
    def tail : Nothing = throw new NoSuchElementException("Nil.tail")
}

然后我尝试创建diff示例,除非我想创建像List(4,5,List(2,3))这样的示例,否则大多数都会工作。

  val list1 = new Cons(4, new Cons(5, new Nil)) //worked
  val list = new Cons(1, new Cons(2, new Cons(3, new Nil))) //worked

  val mList = new Cons(list1, new Cons(list, new Nil)) //worked

  val nList = new Cons(4, new Cons(list, new Nil)) // DID NOT WORK
  // <console>:11: error: type mismatch;
  // found   : Cons[Cons[Int]]
  // required: List[Any]
  // Note: Cons[Int] <: Any, but trait List is invariant in type T.
  // You may wish to define T as +T instead. (SLS 4.5)
  //        val nList = new Cons(4, new Cons(list, new Nil))

有人可以帮我理解我做错了吗?

2 个答案:

答案 0 :(得分:3)

在nList的构造函数中,new Cons(list, new Nil)创建一个List [List [Int]](即Int列表列表)。然后将它与new Cons(4, ...组合,这只适用于List [Int],而不是List [List [Int]],因此类型不匹配。

这应该有效:

val nList = new Cons(new Cons(4, Nil), new Cons(list, new Nil)) // List[List[Int]]

一个侧面点:考虑制作Cons和Nil案例类,然后你可以免费获得一个带有apply方法的伴随对象,允许你从代码中删除所有new

val nList = Cons(Cons(4, Nil), Cons(list, Nil))

答案 1 :(得分:2)

您的问题与类型有关。

在前两个示例中,您有一个整数列表(特别是Cons[Int])。

但是,在第三个示例中,您有一个整体列表的列表(即Cons[Cons[Int]])。这种情况就是这样,因为列表中的每个元素本身都是一个列表(list1list,如上所定义。)

最后一个示例失败,因为传递给第一个Cons的参数是4(一个int)和new Cons(list, new Nil),它是一个Cons[Cons[Int]]。没有类型T,因此构造函数需要此处的第一个参数为T,后者为List[T]

如果你想要一个整数列表,就不需要在另一个list构造函数中“包装”Cons(它构成一个单元素列表,其中该元素本身就是一个列表)。你可以简单地使用:

val nList = new Cons(4, list)