Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
练习:在Scala中实现流_Scala_Functional Programming - Fatal编程技术网

练习:在Scala中实现流

练习:在Scala中实现流,scala,functional-programming,Scala,Functional Programming,我在学习《Scala中的函数式编程》(Functional programming in Scala),特别是在实现一个简单的流特征和伴生对象的部分。作为参考,以下是我们到目前为止在obejct配套文件中的内容 object Stream { def empty[A]: Stream[A] = new Stream[A] { def uncons = None } def cons[A](hd: => A, tl: => Stream[A]):

我在学习《Scala中的函数式编程》(Functional programming in Scala),特别是在实现一个简单的流特征和伴生对象的部分。作为参考,以下是我们到目前为止在obejct配套文件中的内容

object Stream {
  def empty[A]: Stream[A] =
    new Stream[A] {
      def uncons = None
    }

  def cons[A](hd: => A, tl: => Stream[A]): Stream[A] =
    new Stream[A] {
      lazy val uncons = Some((hd, tl))
    }

  def apply[A](as: A*): Stream[A] =
    if (as.isEmpty)
      empty
    else
      cons(as.head, apply(as.tail: _*))
}
到目前为止的特点是:

trait Stream[A] {
  import Stream._

  def uncons: Option[(A, Stream[A])]

  def toList: List[A] = uncons match {
    case None => Nil: List[A]
    case Some((a, as)) => a :: as.toList
  }

  def #::(a: => A) = cons(a, this)

  def take(n: Int): Stream[A] =
    if (n <= 0)
      empty
    else (
      uncons
      map { case (a, as) => a #:: (as take (n - 1)) }
      getOrElse empty
    )
}
不幸的是,我似乎得到了一个我无法追踪的方差错误:

error: type mismatch;  found   : Stream[_2] where type _2 <: A 
required: Stream[A]
Note: _2 <: A, but trait Stream is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
           getOrElse empty
           ^

错误:类型不匹配;found:Stream[_2]where type _2这似乎是类型推断的问题,因为如果显式指定子表达式的类型
uncon map{case(a,as)=>if(f(a))(a#::(as takeWhile f))else empty}

def takeWhile(f: A => Boolean): Stream[A] = {
  val mapped:Option[Stream[A]] = uncons map {
    case (a, as) => if (f(a)) (a #:: (as takeWhile f)) else empty
  }
  mapped getOrElse empty
}

要完成另一个答案,请在这一行中输入
空值

map { case (a, as) => if (f(a)) (a #:: (as takeWhile f)) else empty }

被推断为
empty[Nothing]
,这意味着
(a#::(as takeWhile f))或者empty
被推断为
Stream[Foo谢谢,这是有效的。你知道类型推断器在这种情况下失败的原因吗?在Scala中必须键入中间值是常见的吗(当然,除了像
Nil:List[Int]
这样模棱两可的情况)我不知道为什么它会失败,但这并不常见。尽管有一些已知的限制,例如递归函数或多重返回。也许你应该在邮件列表中询问这个问题。
map { case (a, as) => if (f(a)) (a #:: (as takeWhile f)) else empty }
map { case (a, as) => if (f(a)) (a #:: (as takeWhile f)) else empty[A] }