I am working through some of the exercises in: Functional Programming in Scala specifically problem 5.2. The issue is that with the following code which I have pieced together from the answer key.
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: _*))
}
I get the following in the 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
^
You have 2 problems in this code:
Not explicitly specifying that the empty and cons methods are located in the companion object Stream
To fix this you need to either import Stream._ into your 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
}
}
Or you need to explicitly specify it:
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
}
}
Using the variable names of t and h that are in case class Cons instead of the bound variables of hs and ts.
When you do this:
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)
You are saying that you want to extract the case class parameters as hs and ts respectively and use them in the next code block. It does not matter if they were called h and t in the case class, they will be assigned the names you specify in the match.
Fixing these two issues and your code should compile (I personally tested it with Scala 2.11.5 and Java 1.7, but I don't think it should matter):
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: _*))
}
Related
Was playing with Lazy Structure Stream as below
import Stream._
sealed trait Stream[+A] {
..
def toList: List[A] = this match {
case Empty => Nil
case Cons(h, t) => println(s"${h()}::t().toList"); h()::t().toList
}
def foldRight[B](z: B) (f: ( A, => B) => B) : B = this match {
case Empty => println(s"foldRight of Empty return $z"); z
case Cons(h, t) => println(s"f(${h()}, t().foldRight(z)(f))"); f(h(), t().foldRight(z)(f))
}
..
}
case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
object Stream {
def cons[A](h: => A, t: => Stream[A]): Stream[A] = {
lazy val hd = h
lazy val tl = t
Cons[A](() => hd, () => tl)
}
def empty[A]: Stream[A] = Empty
def apply[A](la: A*): Stream[A] = la match {
case list if list.isEmpty => empty[A]
case _ => cons(la.head, apply(la.tail:_*))
}
}
For a function takeWhile via foldRight i initially wrote:
def takeWhileFoldRight_0(p: A => Boolean) : Stream[A] = {
foldRight(empty[A]) {
case (a, b) if p(a) => println(s"takeWhileFoldRight cons($a, b) with p(a) returns: cons($a, b)"); cons(a, b)
case (a, b) if !p(a) => println(s"takeWhileFoldRight cons($a, b) with !p(a) returns: empty[A]"); empty[A]
}
}
Which when called as:
Stream(4,5,6).takeWhileFoldRight_0(_%2 == 0).toList
result in the following trace:
f(4, t().foldRight(z)(f))
f(5, t().foldRight(z)(f))
f(6, t().foldRight(z)(f))
foldRight of Empty return Empty
takeWhileFoldRight cons(6, b) with p(a) returns: cons(6, b)
takeWhileFoldRight cons(5, b) with !p(a) returns: empty[A]
takeWhileFoldRight cons(4, b) with p(a) returns: cons(4, b)
4::t().toList
res2: List[Int] = List(4)
Then questioning and questioning i figured that it might have been the unapply method in the pattern match that evaluate eagerly.
So i changed to
def takeWhileFoldRight(p: A => Boolean) : Stream[A] = {
foldRight(empty[A]) { (a, b) =>
if (p(a)) cons(a, b) else empty[A]
}
}
which when called as
Stream(4,5,6).takeWhileFoldRight(_%2 == 0).toList
result in the following trace:
f(4, t().foldRight(z)(f))
4::t().toList
f(5, t().foldRight(z)(f))
res1: List[Int] = List(4)
Hence my question:
Is there a way to recover the power of pattern match when working with by-name parameter ?
Said differently case i match parameter that are by-name without evaluating them eagerly ?
Or i have to go to a set of ugly nested "if" :p in that kind of scenario
Take a closer look at this fragment:
def toList: List[A] = this match {
case Empty => Nil
case Cons(h, t) => println(s"${h()}::t().toList"); h()::t().toList
}
def foldRight[B](z: B) (f: ( A, => B) => B) : B = this match {
case Empty => println(s"foldRight of Empty return $z"); z
case Cons(h, t) => println(s"f(${h()}, t().foldRight(z)(f))"); f(h(), t().foldRight(z)(f))
}
..
}
Here h and t in Cons aren't evaluated by unapply - after all unapply returns () => X functions without calling them. But you do. Twice for each match - once for printing and once for passing the result on. And you aren't remembering the result, so any future fold, map, etc would evaluate the function anew.
Depending on what behavior you want to have you should either:
Calculate the results once, right after matching them:
case Cons(h, t) =>
val hResult = h()
val tResult = t()
println(s"${hResult}::tail.toList")
hResult :: tResult.toList
or
not use case class because it cannot memoize the result and you might need to memoize it:
class Cons[A](fHead: () => A, fTail: () => Stream[A]) extends Stream[A] {
lazy val head: A = fHead()
lazy val tail: Stream[A] = fTail()
// also override: toString, equals, hashCode, ...
}
object Cons {
def apply[A](head: => A, tail: => Stream[A]): Stream[A] =
new Cons(() => head, () => tail)
def unapply[A](stream: Stream[A]): Option[(A, Stream[A])] = stream match {
case cons: Cons[A] => Some((cons.head, cons.tail)) // matches on type, doesn't use unapply
case _ => None
}
}
If you understand what you're doing you could also create a case class with overridden apply and unapply (like above) but that is almost always a signal that you shouldn't use a case class in the first place (because most likely toString, equals, hashCode, etc would have nonsensical implementation).
So I'm following fpinscala and I have this Object:
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
object List {
def sum(ints: List[Int]): Int = ints match {
case Nil => 0
case Cons(x, xs) => x + sum(xs)
}
def product(ds: List[Double]): Double = ds match {
case Nil => 1
case Cons(x, xs) => x * product(xs)
}
def apply[A](as: A*): List[A] =
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
def tail[A](as: List[A]): List[A] = as match {
case Nil => as
case Cons(_, xs) => xs
}
def setHead[A](as: List[A], a: A): List[A] = as match {
case Nil => Cons(a, Nil)
case Cons(_, xs) => Cons(a, xs)
}
def main(args: Array[String]): Unit =
println(tail(List(1,2,3)))
}
When I try to run main I get:
error: type mismatch;
found : List[Int] (in scala.collection.immutable)
required: List[?] (in <empty>)
println(tail(List[Int](1,2,3)))
I have followed the book pretty exactly so I don't know what I'm missing here. It says you should now be able to call List(1, 2, 3, 4) or List("hello", "goodbye") with no issues. But I can't pass that to the function? Some insight on what I'm missing would be appreciated.
The code compiles correctly, the only problem I see is that you are declaring the main method in the List companion object and that is incorrect, you should move it to other object:
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
object List {
def sum(ints: List[Int]): Int = ints match {
case Nil => 0
case Cons(x, xs) => x + sum(xs)
}
def product(ds: List[Double]): Double = ds match {
case Nil => 1
case Cons(x, xs) => x * product(xs)
}
def apply[A](as: A*): List[A] =
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
def tail[A](as: List[A]): List[A] = as match {
case Nil => as
case Cons(_, xs) => xs
}
def setHead[A](as: List[A], a: A): List[A] = as match {
case Nil => Cons(a, Nil)
case Cons(_, xs) => Cons(a, xs)
}
}
object Main {
def main(args: Array[String]): Unit =
println(List.tail(List(1,2,3)))
}
I am trying to understand how Stream works and have following Stream implementation:
sealed trait Stream[+A] {
def toList: List[A] = {
#annotation.tailrec
def go(s: Stream[A], acc: List[A]): List[A] = s match {
case Cons(h, t) => go(t(), h() :: acc)
case _ => acc
}
go(this, List()).reverse
}
def foldRight[B](z: => B)(f: (A, => B) => B): B =
this match {
case Cons(h, t) => f(h(), t().foldRight(z)(f))
case _ => z
}
def map[B](f: A => B): Stream[B] =
this.foldRight(Stream.empty[B])((x, y) => Stream.cons(f(x), y))
def filter(f: A => Boolean): Stream[A] =
this.foldRight(Stream.empty[A])((h, t) => if (f(h)) Stream.cons(h, t) else t)
}
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, t1: => Stream[A]): Stream[A] = {
lazy val head = hd
lazy val tail = t1
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: _*))
}
and the code that is using Stream:
Stream(1,2,3,4).map((x) => {
println(x)
x + 10
}).filter((x) => {
println(x)
x % 2 == 0
}).toList
as output I've got:
1
11
2
12
3
13
4
14
res4: List[Int] = List(12, 14)
As you can see on the output, there is no intermediate result, the source will be pass one for one, how is that possible?
I can not image, how does it work.
Let's take a look at what the methods you used do on Stream:
map and filter are both implemented with foldRight. To make it clearer, let's inline foldRight inside map (the same can be done with filter), using the referential transparency principle:
def map[B](f: A => B) = this match {
case Cons(h, t) => Stream.cons(f(h()), t().map(f))
case _ => Empty
}
Now, where in this code is f evaluated? Never, since Stream.cons parameters are call-by-name, so we only give the description for the new stream, not its values.
Once you are convinced of this fact, you can easily see that the same will apply for filter, so we can move forward to toList.
It will evaluate each element in the Stream, putting the values in a List that will be reversed at the end.
But evaluating an element of the Stream which has been filtered and mapped is precisely reading the description of the values, so the actual functions are evaluated here. Hence the console output in order: first the map function is called then the filter function, for each element, one at a time (since we are now on the lazily mapped and filtered Stream).
I have a Stream trait, that contains following method:
sealed trait Stream[+A] {
def takeWhile2(f: A => Boolean): Stream[A] =
this.foldRight(Stream.empty[A])((x, y) => {
if (f(x)) Stream.cons(x, y) else Stream.empty
})
#annotation.tailrec
final def exists(p: A => Boolean): Boolean = this match {
case Cons(h, t) => p(h()) || t().exists(p)
case _ => false
}
}
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, t1: => Stream[A]): Stream[A] = {
lazy val head = hd
lazy val tail = t1
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: _*))
}
Take a look at takeWhile2 body, it calls foldRight function.
When I would pass Stream.empty instead of Stream.empty[A], I would get compiler error, why?
That's because foldRight infers its type parameter from its first parameter list (ie its zero element).
Since this first element is Stream.empty, the type inferred is Stream[Nothing], and so it expects the second parameter to be a (A, Stream[Nothing]) => Stream[Nothing], which is clearly not the case.
The same issue is true with any fold operator on collections, Option, ...
That's because you have casted (x,y) as Stream.empty[A] when f(x) is true but when f(x) is false it will return Stream.empty[Nothing] i.e. if you don't specify a dataType default of Nothing is used. So the Stream[A] (expected return type) doesn't match with returned value of Stream[Nothing]
case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
sealed trait Stream[+A] {
def toList: List[A] = {
val buf = new collection.mutable.ListBuffer[A]
def go(s: Stream[A]): List[A] = s match {
case Cons(h, t) =>
buf += h()
go(t())
case _ => buf.toList
}
go(this)
}
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = Stream.cons(hd, tl)
def empty = Stream.empty
def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] = f(z) match {
case Some((h,t)) => cons(h, unfold(t)(f))
case None => empty
}
def take(n: Int): Stream[A] = unfold((this, n)) {
case (Cons(h, t), 1) => Some((h(), (empty, 0)))
case (Cons(h, t), n) if n > 1 => Some((h(), (t(), n-1)))
case (Empty, 0) => None
}
}
object Stream {
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = Cons(() => hd, () => tl)
def empty[A]: Stream[A] = Empty
val ones: Stream[Int] = Stream.cons(1, ones)
}
object StreamTest {
def main(args: Array[String]) {
//why compile error: forward reference extends over definition of value ones
/*val ones: Stream[Int] = Stream.cons(1, ones)
println(ones.take(5).toList)*/
println(Stream.ones.take(5).toList)
}
}
why compile error?: forward reference extends over definition of value ones
in pair object 'Stream',
val ones: Stream[Int] = Stream.scons(1, ones) is ok
but in main method, it's not ok (but... same synthetics!)
Local vals are not members.
For your test code, do this:
object StreamTest extends App {
//def main(args: Array[String]) {
//why compile error: forward reference extends over definition of value ones
val ones: Stream[Int] = Stream.cons(1, ones)
println(ones.take(5).toList)
println(Stream.ones.take(5).toList)
//}
}
The restriction in blocks is worded in the spec here, where the other advice is to make it a lazy val in the block, which has the same effect.
The forward reference is in Cons[+A]...which is referenced in this line:
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = Cons(() => hd, () => tl)
Try to move
case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
into the companion object.