我正在关注Functional programming in Scala
这本书,特别是您实现简单的Stream特征和伴侣对象的部分。作为参考,这里是我们至今在同伴obejct练习:在Scala中实现Stream
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
)
}
下一个练习要求我写一个实施takeWhile
,我认为以下会做
def takeWhile(f: A => Boolean): Stream[A] = (
uncons
map { case (a, as) => if (f(a)) (a #:: (as takeWhile f)) else empty }
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
^
我可以添加一个方差注释,但在此之前我想了解这里出了什么问题。有什么建议么?
谢谢,这个作品。你有什么线索为什么类型推理在这种情况下失败?在Scala中常见的是必须输入中间值(当然,除非像'Nil:List [Int]')这样的不明确的情况除外) – Andrea 2012-08-16 10:18:25
我不知道它为什么会失败,但并不常见。尽管有一些已知的限制,例如递归函数或多个返回值。也许你应该在邮件列表中询问这个问题。 – 2012-08-16 10:25:20