I have a MyStream-trait:
trait MyStream[+A] {
def uncons: Option[(A, MyStream[A])]
def isEmpty: Boolean = uncons.isEmpty
}
object MyStream {
def empty[A]: MyStream[A] =
new MyStream[A] { def uncons = None }
def cons[A](hd: => A, tl: => MyStream[A]): MyStream[A] =
new MyStream[A] { lazy val uncons = Some((hd, tl)) }
def apply[A](as: A*): MyStream[A] = if (as.isEmpty) empty
else cons(as.head, apply(as.tail: _*))
}
How can I use the uncons operator for pattern matching like:
def takeWhile(f: A => Boolean): MyStream[A] = this match {
case uncons(h,t) if f(h()) => cons(h(), t() takeWhile f)
case _ => empty
}
I am very new to Scala so I need a little help here.
Thanks!
How about this:
trait MyStream[+A] {
def uncons: Option[(A, MyStream[A])]
def isEmpty: Boolean = uncons.isEmpty
def takeWhile(f: A => Boolean): MyStream[A] = this match {
case MyStream(h, t) if f(h) => MyStream.cons(h, t takeWhile f)
case _ => MyStream.empty
}
#tailrec
final def foldLeft[B](z: B)(op: (B, A) => B): B =
this match {
case MyStream(h, t) => t.foldLeft(op(z, h))(op)
case _ => z
}
override def toString = this.foldLeft("") { case (acc, x) => acc + x }
}
object MyStream {
def empty[A]: MyStream[A] =
new MyStream[A] {
def uncons = None
}
def cons[A](hd: => A, tl: => MyStream[A]): MyStream[A] =
new MyStream[A] {
lazy val uncons = Some((hd, tl))
}
def apply[A](as: A*): MyStream[A] =
if (as.isEmpty) empty
else cons(as.head, apply(as.tail: _*))
def unapply[A](stream: MyStream[A]) = stream.uncons
}
object TestMyStream extends App {
import MyStream._
val s = cons(1, cons(2, cons(3, empty)))
println("All: " + s)
println("Take < 3: " + s.takeWhile(_ < 3))
}
prints:
All: 123
Take < 3: 12
Related
When I try to compile the following I get:
"not found: value cons" and "not found: value empty" for the take and drop method definitions.
Somehow the trait doesn't "see" the companion object?
I'm using IntelliJ IDEA, in case that matters.
import scala.annotation.tailrec
object Run extends App {
sealed trait StreamRed[+A] {
def headOption: Option[A] = this match {
case Empty => None
case Cons(h,t) => Some(h())
}
def toList: List[A] = {
#tailrec
def toListRec(stream: StreamRed[A], accumulated: List[A]): List[A] = this match {
case Cons(h,t) => toListRec(t(), h()::accumulated)
case _ => accumulated
}
toListRec(this, List()).reverse
}
def take(n: Int): StreamRed[A] = this match {
case Cons(h, t) if n > 1 => cons(h(), t().take(n - 1))
case Cons(h, _) if n == 1 => cons(h(), empty)
case _ => empty
}
#tailrec
def drop(n: Int): StreamRed[A] = this match {
case Cons(_,t) if n > 0 => t().drop(n-1)
case _ => empty
}
}
case object Empty extends StreamRed[Nothing]
case class Cons[+A](h: () => A, t: () => StreamRed[A]) extends StreamRed[A]
object StreamRed {
def cons[A](hd: => A, tl: => StreamRed[A]): StreamRed[A] = {
lazy val head = hd
lazy val tail = tl
Cons(() => head, () => tail)
}
def empty[A]: StreamRed[A] = Empty
def apply[A](as: A*): StreamRed[A] =
if (as.isEmpty) empty else cons(as.head, apply(as.tail: _*))
}
}
Companions can see each other's members in the sense that access modifiers are not a problem.
class A {
private def foo: Unit = ()
A.bar
}
object A {
private def bar: Unit = ()
(new A).foo
}
is ok on contrary to
class A {
private def foo: Unit = ()
B.bar
}
object B {
private def bar: Unit = ()
(new A).foo
}
(But if you replace private with private[this] the former won't work either.)
But this doesn't mean that namespaces are imported automatically.
class A {
private def foo: Unit = ()
import A._
bar
}
object A {
private def bar: Unit = ()
val a = new A
import a._
foo
}
is ok on contrary to
class A {
private def foo: Unit = ()
bar
}
object A {
private def bar: Unit = ()
foo
}
Anyway a method has to know its this.
I want to write an unfold for streams.
Fails to compile, because it's not tail recursive.
#annotation.tailrec
def unfold[A, B](a: A)(f: A => Option[(A, B)]): Stream[B] =
f(a).map { case (a, b) => b #:: unfold(a)(f) }.getOrElse(Stream.empty)
... not really working either. (Not lazy)
def unfold[A, B](a: A)(f: A => Option[(A, B)]): Stream[B] = {
#annotation.tailrec
def go(state: A, next: Stream[B]): Stream[B] = {
f(state) match {
case Some((a, b)) => go(a, b #:: next)
case None => Stream.empty
}
}
go(a, Stream.empty)
}
// unfold: [A, B](a: A)(f: A => Option[(A, B)])Stream[B]
unfold(0)(i => Some((i+1, i))).take(10).toList
// java.lang.OutOfMemoryError: GC overhead limit exceeded
// at .$anonfun$res3$1(<console>:18)
// at .$anonfun$res3$1$adapted(<console>:18)
// at $$Lambda$1543/299219071.apply(Unknown Source)
// at .go$1(<console>:19)
// at .unfold(<console>:24)
// ... 27 elided
Kinda ugly, via Iterator.
def unfold[A, B](a: A)(f: A => Option[(A, B)]): Stream[B] = {
new Iterator[B] {
private var state: Option[A] = Some(a)
private var nextResult: Option[B] = None
def next: B =
nextResult.getOrElse(
throw new NoSuchElementException("next on empty iterator"))
def hasNext: Boolean = {
if (nextResult.isDefined) {
true
} else {
state match {
case Some(s) =>
f(s) match {
case Some((nextState, produced)) =>
nextResult = Some(produced)
state = Some(nextState)
true
case None => false
}
case None => false
}
}
}
}.toStream
}
def unfold[A, B](a: A)(f: A => Option[(A, B)]): Stream[B] =
f(a).map { case (a, b) => b #:: unfold(a)(f) }.getOrElse(Stream.empty)
This is correct and lazy (although some REPLs might attempt to print all the stream).
Scala streams have their tails evaluated lazily. I don't think you can affect the tail of a stream in a lazy fashion in a tail-recursive way. However, it's pointless because laziness gives you stack safety:
assert(unfold(0) { _ => Some((0, 0)) } .toString == "Stream(0, ?)")
assert {
try {
unfold(0) { _ => Some((0, 0)) }.take(1000000).toList
true
} catch {
case _: StackOverflowError => false
}
}
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.
Hello I'm reading the book called "Functional Programming in Scala". Book had code like this
trait Stream[+A] {
def uncons: Option[(A, Stream[A])]
def isEmpty: Boolean = uncons.isEmpty
}
object Stream {
...
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] =
new Stream[A] {
lazy val uncons = Some((hd, tl))
}
...
it says that hd: => A syntax is making this a lazy val
But the code in the github repo had something like this
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
}
}
case class Cons[+A](h: ()=>A, t: () => Stream[A]) extends Stream[A]
What is the difference between h: =>A and h: ()=>A.
Why is the second part of code has () after argument like go(t(), h(), :: acc)
How is it possible to create Enumerator for BufferedReader?
I found rather old article: http://apocalisp.wordpress.com/2010/10/17/scalaz-tutorial-enumeration-based-io-with-iteratees/ and it looks like it doesn't work with Scalaz 6.0.4
I try to create Enumerator based on example from here: Idiomatic construction to check whether a collection is ordered
implicit val ListEnumerator = new Enumerator[List] {
def apply[E, A](e: List[E], i: IterV[E, A]): IterV[E, A] = e match {
case List() => i
case x :: xs => i.fold(done = (_, _) => i,
cont = k => apply(xs, k(El(x))))
}
}
But I can't understand how to combine IO monad with Enumerator
What's wrong with RĂșnar's article? The following version is working for me (Scalaz 6.0.4):
object FileIteratee {
def enumReader[A](r: BufferedReader, it: IterV[String, A]) : IO[IterV[String, A]] = {
def loop: IterV[String, A] => IO[IterV[String, A]] = {
case i#Done(_, _) => i.pure[IO]
case i#Cont(k) => for {
s <- r.readLine.pure[IO]
a <- if (s == null) i.pure[IO] else loop(k(El(s)))
} yield a
}
loop(it)
}
def bufferFile(f: File) = new BufferedReader(new FileReader(f)).pure[IO]
def closeReader(r: Reader) = r.close().pure[IO]
def bracket[A,B,C](init: IO[A], fin: A => IO[B], body: A => IO[C]): IO[C] =
for {
a <- init
c <- body(a)
_ <- fin(a)
} yield c
def enumFile[A](f: File, i: IterV[String, A]) : IO[IterV[String, A]] =
bracket(bufferFile(f),
closeReader(_: BufferedReader),
enumReader(_: BufferedReader, i))
}