我是Scala的新手,我正在阅读Scala中的函数式编程书,在他们的一个练习中,我遇到了两个编译错误,我不明白我为什么会这样做那些。 我在下面的代码中遇到以下两个错误:
error: value toList is not a member of Chapter5.Stream[Int]
val list : List[Int] = st.toList
^
Stream.scala:22: error: constructor cannot be instantiated to expected type;
found : Chapter5.Cons[A]
required: Chapter5.Stream.type
case Cons(h,t) => h() :: t().toList
^
two errors found
这是特征和伴侣对象:
package Chapter5
sealed trait Stream[+A]
case object Empty extends Stream[Nothing]
case class Cons[+A](h : () => A, t : () => Stream[A]) extends Stream[A]
object Stream{
def cons[A](hd : => A, tl: => Stream[A]): Stream[A] = {
lazy val head = hd
lazy val tail = tl
Cons(() => head, () => tail)
}
def empty[A]: Stream[A] = Empty
def apply[A](as: A*): Stream[A] = {
if (as.isEmpty) empty else cons(as.head, apply(as.tail: _*))
}
def toList[A]: List[A] = this match{
case Cons(h,t) => h() :: t().toList
case _ => List()
}
}
当我尝试以下列方式调用toList时,我也收到错误:
package Chapter5
object Main {
def main(args : Array[String]) = {
val arr = Array(1,3,4,6)
val st : Stream[Int] = Stream.apply(arr : _*)
val list : List[Int] = st.toList
}
}
对于第一种情况,我根本不理解这些错误:显然我在对象上定义了一个toList方法。对于第二个Cons扩展了Stream特性,所以我不明白为什么我不能使用这样的模式匹配。
答案 0 :(得分:2)
您要在object Stream
中定义这些方法,而不是trait Stream
。 类型的伴随对象(几乎)与类型本身完全无关。与伴随对象及其类型相关的唯一事物是:
private
部分。 (通过声明事物private[this]
可以使这更加严格。)因此,第21行的this
并不意味着"我们正在操作的Stream
",它意味着"这个单身对象,称为{{1} },这几乎与特质无关,也称为Stream
。"同样,在第22行,Stream
没有Stream
方法;它是toList
(伴侣的类型)。
修改Stream.type
以获取流参数:
toList
或将object Stream
def toList[E](stream: Stream[E]): List[E] = stream match {
// !^^^^^^^^^^^^^^^^^! ^!!!!^
}
}
(可能toList
)移至cons
:
trait Stream