1

在遵循我的 Odersky 的 coursera Scala 课程时,我实现了以下列表示例:

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))

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

4

2 回答 2

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从代码中删除所有 s :

val nList = Cons(Cons(4, Nil), Cons(list, Nil))
于 2013-10-02T15:19:01.767 回答
2

你的问题是类型。

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

但是,在第三个示例中,您有一个整数列表列表(即 a Cons[Cons[Int]])。之所以如此,是因为列表中的每个元素本身就是一个列表(list1并且list如上所述)。

最后一个示例失败,因为传递给第一个示例的参数Cons4(an int) 并且new Cons(list, new Nil)是 a Cons[Cons[Int]]。根据构造函数的要求,这里没有T第一个参数是 aT而后者是 aList[T]的类型。

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

val nList = new Cons(4, list)
于 2013-10-02T15:18:28.203 回答