///|
pub fn[A] LazyRec::new(f : (Lazy[A]) -> A) -> LazyRec[A] {
  { repr: LazyBuilder::new(f), memo: None }
}

///|
pub fn[A] LazyRec::modify(self : LazyRec[A], f : (A) -> A) -> Unit {
  self.repr = self.repr.map(f)
  self.memo = None
}

///|
pub fn[A, B] LazyRec::get(self : LazyRec[A], f : (A) -> B) -> B {
  fn aux(lazy_) {
    self.memo = Some(lazy_)
    lazy_.force() |> f
  }

  match self.memo {
    None => aux(self.repr.run())
    Some(lazy_) => aux(lazy_)
  }
}

///|
pub fn[A] LazyRec::force(self : LazyRec[A]) -> A {
  match self.memo {
    None => {
      let lazy_ = self.repr.run()
      self.memo = Some(lazy_)
      lazy_.force()
    }
    Some(lazy_) => lazy_.force()
  }
}

///|
pub impl[T : Show] Show for LazyRec[T] with output(self, logger) {
  self.force().output(logger)
}