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

scalaz.iteratee.EnumeratorP.scala Maven / Gradle / Ivy

The newest version!
package scalaz
package iteratee

import Iteratee._
import Enumeratee2T._

import scala.annotation.tailrec

trait ForallM[P[_[_]]] {
  def apply[F[_]: Monad]: P[F]
}

abstract class EnumeratorP[E, F[_]] { self =>
  def apply[G[_]](implicit MO: MonadPartialOrder[G, F]): EnumeratorT[E, G]

  def map[B](f: E => B): EnumeratorP[B, F] =
    new EnumeratorP[B, F] {
      def apply[G[_]](implicit MO: MonadPartialOrder[G, F]) = {
        import MO._
        self[G].map[B](f)
      }
    }

  def flatMap[B](f: E => EnumeratorP[B, F]) =
    new EnumeratorP[B, F] {
      def apply[G[_]](implicit MO: G |>=| F): EnumeratorT[B, G] = {
        import MO._
        self[G].flatMap[B](e => f(e).apply[G])
      }
    }

  def collect[B](pf: PartialFunction[E, B]) = 
    new EnumeratorP[B, F] {
      def apply[G[_]](implicit MO: G |>=| F): EnumeratorT[B, G] = {
        import MO._
        self[G].collect[B](pf)
      }
    }

  def uniq(implicit ord: Order[E]) = 
    new EnumeratorP[E, F] {
      def apply[G[_]](implicit MO: G |>=| F): EnumeratorT[E, G] = {
        import MO._
        self[G].uniq
      }
    }

  def zipWithIndex = 
    new EnumeratorP[(E, Long), F] {
      def apply[G[_]](implicit MO: G |>=| F): EnumeratorT[(E, Long), G] = {
        import MO._
        self[G].zipWithIndex
      }
    }

  def :^[B](other: EnumeratorP[B, F]): EnumeratorP[(E, B), F] =
    new EnumeratorP[(E, B), F] {
      def apply[G[_]](implicit MO: G |>=| F) = {
        import MO._
        self[G].cross[B](other[G])
      }
    }

  def ^:[B](other: EnumeratorP[B, F]): EnumeratorP[(E, B), F] =
    new EnumeratorP[(E, B), F] {
      def apply[G[_]](implicit MO: G |>=| F) = {
        import MO._
        self[G].cross[B](other[G])
      }
    }

  def join(other: EnumeratorP[E, F])(implicit order: Order[E], m: Monad[F]): EnumeratorP[(E, E), F] =
    EnumeratorP.joinE[E, E, F](m, order.order).apply(self, other)

  def merge(other: EnumeratorP[E, F])(implicit ord: Order[E], m: Monad[F]) =
    EnumeratorP.mergeE[E, F].apply(self, other)
}

trait EnumeratorPFunctions {
  def empty[E, F[_]]: EnumeratorP[E, F] = new EnumeratorP[E, F] {
    def apply[G[_]](implicit MO: MonadPartialOrder[G, F]) = {
      import MO._
      EnumeratorT.empty[E, G]
    }
  }

  def perform[E, F[_], B](f: F[B]): EnumeratorP[E, F] = new EnumeratorP[E, F] {
    def apply[G[_]](implicit MO: MonadPartialOrder[G, F]) = {
      import MO._
      EnumeratorT.perform[E, G, B](MO.promote(f))
    }
  }

  def enumPStream[E, F[_]: Monad](xs : Stream[E]): EnumeratorP[E, F] = new EnumeratorP[E, F] {
    def apply[G[_]](implicit MO: MonadPartialOrder[G, F]): EnumeratorT[E, G] = {
      import MO._
      enumStream[E, G](xs)
    }
  }

  def liftE2[J, K, I, F[_]](e2t: ForallM[({type λ[β[_]] = Enumeratee2T[J, K, I, β]})#λ]): (EnumeratorP[J, F], EnumeratorP[K, F]) => EnumeratorP[I, F] = {
    (e1: EnumeratorP[J, F], e2: EnumeratorP[K, F]) => new EnumeratorP[I, F] {
      def apply[G[_]](implicit MO: MonadPartialOrder[G, F]): EnumeratorT[I, G] =
        new EnumeratorT[I, G] {
          import MO._
          implicit val IOrd = MO.transform[({ type λ[β[_], α] = IterateeT[K, β, α] })#λ]
          lazy val enum1 = e1[({ type λ[α] = IterateeT[K, G, α]})#λ]
          lazy val enum2 = e2[G]

          def apply[A] = {
            (step: StepT[I, G, A]) => iterateeT(((e2t[G].apply(step) &= enum1).run &= enum2).run)
          }
        }
    }
  }

  def cogroupE[J, K, F[_]](implicit M: Monad[F], ord: (J, K) => Ordering) = liftE2[J, K, Either3[J, (J, K), K], F] {
    new ForallM[({type λ[β[_]] = Enumeratee2T[J, K, Either3[J, (J, K), K], β]})#λ] {
      def apply[G[_]: Monad] = cogroupI[J, K, G]
    }
  }

  def joinE[J, K, F[_]](implicit M: Monad[F], ord: (J, K) => Ordering) = liftE2[J, K, (J, K), F] {
    new ForallM[({type λ[β[_]] = Enumeratee2T[J, K, (J, K), β]})#λ] {
      def apply[G[_]: Monad] = joinI[J, K, G]
    }
  }

  def mergeE[E: Order, F[_]: Monad] = liftE2[E, E, E, F] {
    new ForallM[({type λ[β[_]] = Enumeratee2T[E, E, E, β]})#λ] {
      def apply[G[_]: Monad] = mergeI[E, G]
    }
  }

  def mergeAll[E: Order, F[_]: Monad](enumerators: EnumeratorP[E, F]*): EnumeratorP[E, F] = {
    @tailrec def mergeOne(e: EnumeratorP[E, F], es: List[EnumeratorP[E, F]]): EnumeratorP[E, F] = es match {
      case x :: xs => mergeOne(e merge x, xs) 
      case Nil => e
    }   

    enumerators.toList match {
      case x :: xs => mergeOne(x, xs) 
      case Nil => empty[E, F]
    }   
  }
}

trait EnumeratorPInstances {
  implicit def enumeratorPMonoid[E, F[_]]: Monoid[EnumeratorP[E, F]] = new Monoid[EnumeratorP[E, F]] {
    def zero = EnumeratorP.empty[E, F]
    def append(f1: EnumeratorP[E, F], f2: => EnumeratorP[E, F]) =
      new EnumeratorP[E, F] {
        def apply[G[_]](implicit MO: MonadPartialOrder[G, F]) = {
          import MO._
          EnumeratorT.enumeratorTMonoid[E, G].append(f1[G], f2[G])
        }
      }
  }
}

object EnumeratorP extends EnumeratorPFunctions with EnumeratorPInstances

// vim: set ts=4 sw=4 et:




© 2015 - 2025 Weber Informatics LLC | Privacy Policy