Back to Fpinscala

13.Answer

answerkey/laziness/13.answer.md

latest1.6 KB
Original Source
scala
def mapViaUnfold[B](f: A => B): LazyList[B] =
  unfold(this):
    case Cons(h, t) => Some((f(h()), t()))
    case _ => None

def takeViaUnfold(n: Int): LazyList[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 _ => None

def takeWhileViaUnfold(f: A => Boolean): LazyList[A] =
  unfold(this):
    case Cons(h, t) if f(h()) => Some((h(), t()))
    case _ => None

def zipAll[B](that: LazyList[B]): LazyList[(Option[A], Option[B])] =
  unfold((this, that)):
    case (Empty, Empty) => None
    case (Cons(h1, t1), Empty) => Some((Some(h1()) -> None) -> (t1() -> Empty))
    case (Empty, Cons(h2, t2)) => Some((None -> Some(h2())) -> (Empty -> t2()))
    case (Cons(h1, t1), Cons(h2, t2)) => Some((Some(h1()) -> Some(h2())) -> (t1() -> t2()))

def zipWith[B,C](that: LazyList[B])(f: (A,B) => C): LazyList[C] =
  unfold((this, that)):
    case (Cons(h1, t1), Cons(h2, t2)) =>
      Some((f(h1(), h2()), (t1(), t2())))
    case _ => None

// special case of `zipWith`
def zip[B](that: LazyList[B]): LazyList[(A,B)] =
  zipWith(that)((_,_))

def zipWithAll[B, C](that: LazyList[B])(f: (Option[A], Option[B]) => C): LazyList[C] =
  LazyList.unfold((this, that)):
    case (Empty, Empty) => None
    case (Cons(h, t), Empty) => Some(f(Some(h()), Option.empty[B]) -> (t(), empty[B]))
    case (Empty, Cons(h, t)) => Some(f(Option.empty[A], Some(h())) -> (empty[A] -> t()))
    case (Cons(h1, t1), Cons(h2, t2)) => Some(f(Some(h1()), Some(h2())) -> (t1() -> t2()))

def zipAllViaZipWithAll[B](s2: LazyList[B]): LazyList[(Option[A],Option[B])] =
  zipWithAll(s2)((_,_))