package laziness enum LazyList[+A]: case Empty case Cons(h: () => A, t: () => LazyList[A]) // uncomment to be able to use cons(h, t) and empty directly // imports methods from the companion object //import LazyList._ def toList: List[A] = ??? def take(n: Int): LazyList[A] = ??? //This can be tailrecursive. Uncomment below to let the compiler check for it. //@annotation.tailrec def drop(n: Int): LazyList[A] = ??? // Methods shown during lecture def headOption: Option[A] = this match case Cons(h, _) => Some(h()) case Empty => None def exists(p: A => Boolean): Boolean = this match case Cons(x, xs) => p(x()) || xs().exists(p) case Empty => false def foldRight[B](z: => B)(f: (A, => B) => B): B = this match case Cons(x, xs) => f(x(), xs().foldRight(z)(f)) case Empty => z object LazyList: // companion object def fibs: LazyList[Int] = // tip: write a recursive def here and call it with some start values ??? def unfold[A, S](z: S)(f: S => Option[(A, S)]): LazyList[A] = ??? def fibsViaUnfold: LazyList[Int] = ??? // Methods shown during Lecture def cons[A](h: => A, t: => LazyList[A]): LazyList[A] = lazy val head = h lazy val tail = t Cons(() => head, () => tail) def empty[A]: LazyList[A] = Empty def apply[A](as: A*): LazyList[A] = if as.isEmpty then empty else cons(as.head, apply(as.tail: _*)) val ones: LazyList[Int] = cons(1, ones)