All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scalaz.Iteratee.scala Maven / Gradle / Ivy

// Legacy implementation of iteratees, for compatibility with Scalaz 6 */
package scalaz
import Scalaz._

/** The input to an iteratee. */
@deprecated("Scalaz 6 compatibility. Migrate to scalaz.iteratee.", "7.0.0")
sealed trait Input[E] {
  def apply[Z](empty: => Z, el: (=> E) => Z, eof: => Z): Z
  def map[D](f: E => D): Input[D] =
    apply(IterV.Empty.apply[D], e => IterV.El(f(e)), IterV.EOF.apply[D])
}

/** A pure iteratee computation which is either done or needs more input */
@deprecated("Scalaz 6 compatibility. Migrate to scalaz.iteratee.", "7.0.0")
sealed trait IterV[E, A] {
  import IterV._

  def fold[Z](done: (=> A, => Input[E]) => Z, cont: (Input[E] => IterV[E, A]) => Z): Z
  def apply[F[_]](f: F[E])(implicit e: Enumerator[F]): IterV[E, A] = e(f, this)
  def run: A = {
    def runCont(i: IterV[E, A]) = i.fold(done = (x, _) => Some(x), cont = _ => None)
    fold(done = (x, _) => x,
          cont = k => runCont(k(EOF[E])).getOrElse(sys.error("Diverging iteratee!")))
  }
  def drop1First: IterV[E, A] = drop(1) flatMap (_ => this)
  def feed(e: Input[E]): IterV[E, A] = fold((_, _) => this, k => k(e))
  def mapInput(f: Input[E] => Input[E]): IterV[E, A] =
    fold((a, e) => Done(a, f(e)), (k => Cont(i => k(f(i)))))
  def filterInput(p: E => Boolean): IterV[E, A] =
    mapInput {
      case i@El(e) => if (p(e)) i else Empty.apply
      case x => x
    }
  def zipWith[B, C](eb: IterV[E, B], f: (A, B) => C): IterV[E, C] = {
    (this, eb) match {
      case (Cont(k), Cont(l)) => Cont(ie => k(ie).zipWith(l(ie), f))
      case (Cont(k), b) => Cont(ie => k(ie).zipWith(b, f))
      case (a, Cont(k)) => Cont(ie => a.zipWith(k(ie), f))
      case (Done(a, e), Done(b, _)) => Done(f(a, b), e)
    }
  }

  /** An iteratee that sends itself the EOF signal after `n` inputs. */
  def take(n: Int): IterV[E, A] =
    fold((a, i) => Done(a, i),
         k => if (n <= 0) k(EOF.apply) else Cont(i => i(
           k(i).take(n),
           e => k(i).take(n - 1),
           k(i)
         )))

  /** Lift into a monadic iteratee, in the Id monad. */
  def lift: Iteratee[Id, E, A] =
    fold(done = (a, e) => Iteratee[Id, E, A](DoneM(a, e)),
         cont = k => Iteratee[Id, E, A](ContM(i => k(i).lift)))

  def flatMap[B](f: A => IterV[E, B]): IterV[E, B] = this.fold(
      done = (x, str) => f(x).fold(
        done = (x2, _) => Done(x2, str),
        cont = _(str)),
      cont = k => Cont(str2 => k(str2) flatMap f))

  def map[B](f: A => B): IterV[E, B] = flatMap(a => Done(f(a), Empty[E]))
}

/** Monadic Iteratees */
@deprecated("Scalaz 6 compatibility. Migrate to scalaz.iteratee.", "7.0.0")
sealed trait IterVM[M[+_], E, A] {
  def fold[Z](done: (=> A, => Input[E]) => Z, cont: (Input[E] => Iteratee[M, E, A]) => Z): Z
}

@deprecated("Scalaz 6 compatibility. Migrate to scalaz.iteratee.", "7.0.0")
case class Iteratee[M[+_], E, A](value: M[IterVM[M, E, A]]) {
  import IterV._

  def apply(es: StreamT[M, E])(implicit M: Monad[M]): M[A] = for {
    i <- value
    p <- es.uncons
    v <- i.fold((a, e) => M.pure(a),
                k => p match {
                  case Some((h, t)) => k(El(h))(t)
                  case None => k(EOF[E]).value.map(
                    _.fold((a, e) => a, _ => sys.error("Diverging Iteratee")))
                })
  } yield v

  def lower(f: M ~> Id)(implicit M: Monad[M]): M[IterV[E, A]] = for {
    v <- value
    a <- M.pure(v match {
      case DoneM(a, e) => Done(a, e)
      case ContM(k) => Cont((e: Input[E]) => f(k(e).lower(f)))
    })
  } yield a

  def xmap[D](f: D => E, g: E => D)(implicit M: Monad[M]): Iteratee[M, D, A] = Iteratee[M, D, A](for {
    v <- value
    h <- M.pure(v.fold((a, e) => DoneM[M, D, A](a, e map g),
                k => ContM[M, D, A]((d: Input[D]) =>
                  k(d map f).xmap(f, g))))
  } yield h)

  def map[B](f: A => B)(implicit M: Functor[M]): Iteratee[M, E, B] =
    Iteratee[M, E, B](M.map(value)((x: IterVM[M, E, A]) => x.fold((a, e) => DoneM[M, E, B](f(a), e), k => ContM[M, E, B](e => k(e).map(f)))))

  def run(implicit M: Monad[M]): M[A] = {
    def runCont(i: Iteratee[M, E, A]) = for {
      v <- i.value
    } yield v.fold(done = (x, _) => Some(x), cont = _ => None)
    for {
      v <- value
      t <- v.fold(done = (x, _) => M.point(Some(x)),
                  cont = k => runCont(k(EOF[E])))
    } yield t.getOrElse(sys.error("Diverging iteratee!"))
  }
}

/** An Enumerator[F] feeds data from an F to an iteratee */
@deprecated("Scalaz 6 compatibility. Migrate to scalaz.iteratee.", "7.0.0")
trait Enumerator[F[_]] {
  def apply[E, A](f: F[E], i: IterV[E, A]): IterV[E, A]
}

@deprecated("Scalaz 6 compatibility. Migrate to scalaz.iteratee.", "7.0.0")
object IterV {

  case class OptionSyntax[A](value: Option[A]) {
    /**
     * Returns a Done iteratee with the given value if the Option is not defined, otherwise runs the given function.
     */
    def iterDoneOr[B](b: => B, f: A => IterV[A, B]): IterV[A, B] = value match {
      case None => IterV.Done(b, IterV.EOF.apply)
      case Some(a) => f(a)
    }
  }

  implicit def wrapOptionSyntax[A](value: Option[A]): OptionSyntax[A] = OptionSyntax(value)

  implicit def iterVMonad[E]: Monad[({type λ[α] = IterV[E,α]})#λ] = new Monad[({type λ[α] = IterV[E,α]})#λ] {
    def bind[A,B](a: IterV[E, A])(f: A => IterV[E, B]) = a.flatMap(f)
    def point[A](a: => A): IterV[E, A] = Done(a, Empty[E])
  }

  /** An EnumeratorM[M, _, _] feeds data in a monad M to an iteratee */
  type EnumeratorM[M[_], E] = ({type λ[α] = IterV[E, α]})#λ ~> ({type λ[α] = M[IterV[E, α]]})#λ

  /** A computation that has finished */
  object Done {
    def apply[E, A](a: => A, i: => Input[E]): IterV[E, A] = new IterV[E, A] {
      def fold[Z](done: (=> A, => Input[E]) => Z,
                  cont: (Input[E] => IterV[E, A]) => Z): Z = done(a, i)
    }
    def unapply[E, A](r: IterV[E, A]): Option[(A, Input[E])] =
      r.fold[Option[(A,Input[E])]](
        done = (a, i) => Some((a, i)),
        cont = f => None)
  }

  /** A computation that takes an element from an input to yield a new computation */
  object Cont {
    def apply[E, A](f: Input[E] => IterV[E, A]): IterV[E, A] = new IterV[E, A] {
      def fold[Z](done: (=> A, => Input[E]) => Z,
                  cont: (Input[E] => IterV[E, A]) => Z): Z = cont(f)
    }
    def unapply[E, A](r: IterV[E, A]): Option[Input[E] => IterV[E, A]] =
      r.fold[Option[Input[E] => IterV[E, A]]](
        done = (a, i) => None,
        cont = Some(_))
  }

  /** A monadic computation that has finished */
  object DoneM {
    def apply[M[+_], E, A](a: => A, i: => Input[E]): IterVM[M, E, A] = new IterVM[M, E, A] {
      def fold[Z](done: (=> A, => Input[E]) => Z,
                  cont: (Input[E] => Iteratee[M, E, A]) => Z): Z = done(a, i)
    }
    def unapply[M[+_], E, A](r: IterVM[M, E, A]): Option[(A, Input[E])] =
      r.fold[Option[(A, Input[E])]](
        done = (a, i) => Some((a, i)),
        cont = f => None)
  }

  object ContM {
    def apply[M[+_], E, A](f: Input[E] => Iteratee[M, E, A]): IterVM[M, E, A] = new IterVM[M, E, A] {
      def fold[Z](done: (=> A, => Input[E]) => Z,
                  cont: (Input[E] => Iteratee[M, E, A]) => Z): Z = cont(f)
    }
    def unapply[M[+_], E, A](r: IterVM[M, E, A]): Option[Input[E] => Iteratee[M, E, A]] =
      r.fold[Option[Input[E] => Iteratee[M, E, A]]](
        done = (a, i) => None,
        cont = f => Some(f))
  }

  /** An iteratee that consumes the head of the input */
  def head[E] : IterV[E, Option[E]] = {
    def step(s: Input[E]): IterV[E, Option[E]] =
      s(el = e => Done(Some(e), Empty[E]),
        empty = Cont(step),
        eof = Done(None, EOF[E]))
    Cont(step)
  }

  /** An iteratee that returns the first element of the input */
  def peek[E] : IterV[E, Option[E]] = {
    def step(s: Input[E]): IterV[E, Option[E]]
      = s(el = e => Done(Some(e), s),
          empty = Cont(step),
          eof = Done(None, EOF[E]))
    Cont(step)
  }

  /** Peeks and returns either a Done iteratee with the given value or runs the given function with the peeked value */
  def peekDoneOr[A, B](b: => B, f: A => IterV[A, B]): IterV[A, B] =
    peek[A] flatMap (_.iterDoneOr(b, f))

  /** An iteratee that skips the first n elements of the input */
  def drop[E](n: Int): IterV[E, Unit] = {
    def step(s: Input[E]): IterV[E, Unit] =
      s(el = _ => drop(n - 1),
        empty = Cont(step),
        eof = Done((), EOF[E]))
    if (n == 0) Done((), Empty[E])
    else Cont(step)
  }

  /** An iteratee that counts and consumes the elements of the input */
  def length[E] : IterV[E, Int] = {
    def step(acc: Int)(s: Input[E]): IterV[E, Int] =
      s(el = _ => Cont(step(acc + 1)),
        empty = Cont(step(acc)),
        eof = Done(acc, EOF[E]))
    Cont(step(0))
  }

  /**
   * Takes while the given predicate holds, appending with the given monoid.
   */
  def takeWhile[A, F[_]](pred: A => Boolean)(implicit mon: Monoid[F[A]], pr: Applicative[F]): IterV[A, F[A]] = {
    def peekStepDoneOr(z: F[A]) = peekDoneOr(z, step(z, _: A))

    def step(acc: F[A], a: A): IterV[A, F[A]] = {
      if (pred(a))
        drop(1).flatMap(_ => peekStepDoneOr(acc |+| pr.point(a)))
      else
        Done(acc, EOF.apply)
    }
    peekStepDoneOr(mzero[F[A]])
  }

  /**
   * Produces chunked output split by the given predicate.
   */
  def groupBy[A, F[_]](pred: (A, A) => Boolean)(implicit mon: Monoid[F[A]], pr: Applicative[F]): IterV[A, F[A]] = {
    IterV.peek flatMap {
      case None => Done(mzero[F[A]], Empty[A])
      case Some(h) => takeWhile(pred(_, h))
    }
  }

  /**
   * Repeats the given iteratee by appending with the given monoid.
   */
  def repeat[E, A, F[_]](iter: IterV[E,A])(implicit mon: Monoid[F[A]], pr: Applicative[F]): IterV[E, F[A]] = {
    def step(acc: F[A])(s: Input[E]): IterV[E, F[A]] =
      s(el = e => iter.fold(
          (a, _) => Cont(step(acc |+| pr.point(a))),
          k => k(El(e)).fold(
            (a, _) => Cont(step(acc |+| pr.point(a))),
            (k2) => Cont((in: Input[E]) => for {
                h <- k2(in)
                t <- repeat(iter)(mon, pr)
              } yield acc |+| pr.point(h) |+| t
            )
          )),
        empty = Cont(step(acc)),
        eof = Done(acc, EOF.apply))
    Cont(step(mzero[F[A]]))
  }

  /**
   * Iteratee that collects all inputs with the given monoid.
   */
  def collect[A, F[_]](implicit r: Reducer[A, F[A]]): IterV[A, F[A]] = {
    import r._
    def step(acc: F[A])(s: Input[A]): IterV[A, F[A]] =
        s(el = e => Cont(step(snoc(acc, e))),
          empty = Cont(step(acc)),
          eof = Done(acc, EOF.apply))
    Cont(step(mzero[F[A]]))
  }

  /**
   * Iteratee that collects all inputs in reverse with the given reducer.
   *
   * This iteratee is useful for F[_] with efficient cons, i.e. List.
   */
  def reversed[A, F[_]](implicit r: Reducer[A, F[A]]): IterV[A, F[A]] = {
    def step(acc: F[A])(s: Input[A]): IterV[A, F[A]] =
        s(el = e => Cont(step(r.cons(e, acc))),
          empty = Cont(step(acc)),
          eof = Done(acc, EOF.apply))
    Cont(step(r.monoid.zero))
  }

  /**
   * Iteratee that sums the inputs with a given reducer.
   */
  def sum[A, B](implicit r: Reducer[A, B]): IterV[A, B] = {
    def step(acc: B)(s: Input[A]): IterV[A, B] =
        s(el = e => Cont(step(r.snoc(acc, e))),
          empty = Cont(step(acc)),
          eof = Done(acc, EOF.apply))
    Cont(step(r.monoid.zero))
  }

  /** Input that has no values available */
  object Empty {
    def apply[E] : Input[E] = new Input[E] {
      def apply[Z](empty: => Z, el: (=> E) => Z, eof: => Z): Z = empty
    }
    def unapply[E](r: Input[E]): Boolean =
        r.apply[Either[Input[E], Boolean]](
          empty = Right(true),
          el = e => Left(El(e)),
          eof = Left(EOF[E])).fold(x => false, x => x)
  }

  /** Input that has a value available  */
  object El {
    def apply[E](e0: => E): Input[E] = new Input[E] {
      def apply[Z](empty: => Z, el: (=> E) => Z, eof: => Z): Z = el(e0)
    }
    def unapply[E](r: Input[E]): Option[E] =
      r.apply[Either[Input[E], (E)]](
        empty = Left(Empty[E]),
        el = e => Right(e),
        eof = Left(EOF[E])).right.toOption
  }

  /** Input that is exhausted */
  object EOF {
    def apply[E] : Input[E] = new Input[E] {
      def apply[Z](empty: => Z, el: (=> E) => Z, eof: => Z): Z = eof
    }
    def unapply[E](r: Input[E]): Boolean =
      r.apply[Either[Input[E], Boolean]](
        empty = Left(Empty[E]),
        el = e => Left(El(e)),
        eof = Right(true)).fold(x => false, x => x)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy