Scala 错误的前向引用

Scala wrong forward reference

我正在完成一些练习:Scala 中的函数式编程特别是问题 5.2。问题是我从答案中拼凑出以下代码。

sealed trait Stream[+A]
{
  def take(n: Int): Stream[A] = this match {
    case Cons(hs, ts) if n > 1 => cons(h(), t().take(n - 1))
    case Cons(hs, _) if n == 1 => cons(h(), empty)
    case _ => empty
  }

}
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: _*))

}

我在 REPL 中得到以下内容:

<console>:10: error: not found: type A
                    def take(n: Int): Stream[A] = this match {
                                             ^
<console>:11: error: not found: value Cons
                      case Cons(hs, ts) if n > 1 => cons(h(), t().take(n - 1))
                           ^
<console>:11: error: not found: value cons
                      case Cons(hs, ts) if n > 1 => cons(h(), t().take(n - 1))
                                                    ^
<console>:12: error: not found: value Cons
                      case Cons(hs, _) if n == 1 => cons(h(), empty)
                           ^
<console>:12: error: not found: value cons
                      case Cons(hs, _) if n == 1 => cons(h(), empty)
                                                    ^
<console>:13: error: not found: value empty
                      case _ => empty

                            ^

这段代码有 2 个问题:

  1. 未明确指定 emptycons 方法位于伴随对象中 Stream

要解决此问题,您需要 import Stream._ 到您的 class:

sealed trait Stream[+A] {
  import Stream._
  def take(n: Int): Stream[A] = this match {
    case Cons(hs, ts) if n > 1 => cons(hs(), ts().take(n - 1))
    case Cons(hs, _) if n == 1 => cons(hs(), empty)
    case _ => empty
  }
}

或者您需要明确指定:

sealed trait Stream[+A] {
  def take(n: Int): Stream[A] = this match {
    case Cons(hs, ts) if n > 1 => Stream.cons(hs(), ts().take(n - 1))
    case Cons(hs, _) if n == 1 => Stream.cons(hs(), Stream.empty)
    case _ => Stream.empty
  }
}
  1. 使用case class Consth的变量名代替hsts的绑定变量。

当你这样做时:

case Cons(hs, ts) if n > 1 => Stream.cons(hs(), ts().take(n - 1))
case Cons(hs, _) if n == 1 => Stream.cons(hs(), Stream.empty)

你是说你想将 case class 参数分别提取为 hsts 并在下一个代码块中使用它们。在 class 的情况下,它们是否被称为 ht 并不重要,它们将被分配您在匹配中指定的名称。

解决这两个问题,您的代码应该可以编译(我亲自使用 Scala 2.11.5 和 Java 1.7 对其进行了测试,但我认为这无关紧要):

sealed trait Stream[+A] {
  def take(n: Int): Stream[A] = this match {
    case Cons(hs, ts) if n > 1 => Stream.cons(hs(), ts().take(n - 1))
    case Cons(hs, _) if n == 1 => Stream.cons(hs(), Stream.empty)
    case _ => Stream.empty
  }
}
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: _*))

}