【发布时间】:2015-06-25 19:32:06
【问题描述】:
通过 Chiusano Rúnar Bjarnason 编写的出色的“Scala 中的 FP”,尝试通过 #foldRight 懒惰地实现 Stream#takeWhile 时出现奇怪的编译错误。鉴于书中的以下代码(也在GitHub):
trait Stream[+A] {
def foldRight[B](z: => B)(f: (A, => B) => B): B =
this match {
case Cons(h,t) => f(h(), t().foldRight(z)(f))
case _ => z
}
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 takeWhile_fold(p: A => Boolean): Stream[A] =
foldRight(empty[A])((it:A, acc:Stream[A]) => if (p(it)) cons(it, acc) else acc)
但这会导致编译错误:
type mismatch;
[error] found : (A, fpinscala.laziness.Stream[A]) => fpinscala.laziness.Stream[A]
[error] required: (A, => fpinscala.laziness.Stream[A]) => fpinscala.laziness.Stream[A]
[error] foldRight(empty[A])((it:A, acc:Stream[A]) => if (p(it)) cons(it, acc) else ac
但如果我删除 lambda 上的类型,它会起作用:
def takeWhile_fold(p: A => Boolean): Stream[A] =
foldRight(empty[A])((it, acc) => if (p(it)) cons(it, acc) else acc)
Scala 中没有办法在调用代码中声明它应该是一个按名称参数,是吗? (这对调用者来说是否有意义,是接收者决定的,对吧?)尝试:
def takeWhile_fold(p: A => Boolean): Stream[A] =
foldRight(empty[A])((it, acc: => Stream[A]) => if (p(it)) cons(it, acc) else acc)
给出另一个编译错误:
[error] identifier expected but '=>' found.
[error] foldRight(empty[A])((it, acc: => Stream[A]) => if (p(it)) cons(it, acc) else acc)
^
[error] ')' expected but '}' found.
[error] }
[error] ^
[error] two errors found
我已经解决了这个练习,但我的问题是 - 为什么它不适用于显式类型?他们是否以某种方式强制执行严格性,而接收者必须具有非严格性?如果是这样,Scala 中是否有任何语法,以便调用者可以发出“是的,这是按名称参数”的信号?
【问题讨论】:
标签: scala types lazy-evaluation type-inference