错误:构造函数无法实例化为期望的类型

时间:2017-01-02 19:10:48

标签: scala

我是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特性,所以我不明白为什么我不能使用这样的模式匹配。

1 个答案:

答案 0 :(得分:2)

您要在object Stream中定义这些方法,而不是trait Stream类型的伴随对象(几乎)与类型本身完全无关。与伴随对象及其类型相关的唯一事物是:

  1. 他们碰巧有相同的名字。 (从技术上讲,名称在不同的名称空间(类型与术语),所以这只是肤浅的。)
  2. 他们可以看到彼此的private部分。 (通过声明事物private[this]可以使这更加严格。)
  3. 因此,第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