在遵循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))
有人可以帮我理解我做错了吗?
答案 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]]
)。这种情况就是这样,因为列表中的每个元素本身都是一个列表(list1
和list
,如上所定义。)
最后一个示例失败,因为传递给第一个Cons
的参数是4
(一个int)和new Cons(list, new Nil)
,它是一个Cons[Cons[Int]]
。没有类型T
,因此构造函数需要此处的第一个参数为T
,后者为List[T]
。
如果你想要一个整数列表,就不需要在另一个list
构造函数中“包装”Cons
(它构成一个单元素列表,其中该元素本身就是一个列表)。你可以简单地使用:
val nList = new Cons(4, list)