scalaz.iteratee.EnumeratorT.scala Maven / Gradle / Ivy
The newest version!
package scalaz
package iteratee
import effect._
import Iteratee._
import Id._
trait EnumeratorT[E, F[_]] { self =>
def apply[A]: StepT[E, F, A] => IterateeT[E, F, A]
def mapE[I](et: EnumerateeT[E, I, F])(implicit M: Monad[F]): EnumeratorT[I, F] = et run self
def map[B](f: E => B)(implicit ev: Monad[F]): EnumeratorT[B, F] =
EnumerateeT.map[E, B, F](f) run self
def #::(e: E)(implicit F: Monad[F]): EnumeratorT[E, F] = {
new EnumeratorT[E, F] {
def apply[A] = _.mapCont(_(elInput(e))) &= self
}
}
def flatMap[B](f: E => EnumeratorT[B, F])(implicit M1: Monad[F]): EnumeratorT[B, F] =
EnumerateeT.flatMap(f) run self
def flatten[B](implicit ev: E === F[B], F: Monad[F]): EnumeratorT[B, F] =
flatMap(e => EnumeratorT.enumeratorTMonadTrans.liftM(ev(e)))
def bindM[B, G[_]](f: E => G[EnumeratorT[B, F]])(implicit F: Monad[F], G: Monad[G]): F[G[EnumeratorT[B, F]]] = {
import scalaz.syntax.semigroup._
val iter = fold[G[EnumeratorT[B, F]], F, G[EnumeratorT[B, F]]](G.point(EnumeratorT.empty[B, F])) {
case (acc, concat) => G.bind(acc) { en =>
G.map(concat) { append => en |+| append }
}
}
(iter &= self.map(f)).run
}
def collect[B](pf: PartialFunction[E, B])(implicit monad: Monad[F]): EnumeratorT[B, F] =
EnumerateeT.collect[E, B, F](pf) run self
def uniq(implicit ord: Order[E], M: Monad[F]): EnumeratorT[E, F] =
EnumerateeT.uniq[E, F] run self
def zipWithIndex(implicit M: Monad[F]): EnumeratorT[(E, Long), F] =
EnumerateeT.zipWithIndex[E, F] run self
def drainTo[M[_]](implicit M: Monad[F], P: PlusEmpty[M], Z: Applicative[M]): F[M[E]] =
(IterateeT.consume[E, F, M] &= self).run
def reduced[B](b: B)(f: (B, E) => B)(implicit M: Monad[F]): EnumeratorT[B, F] =
new EnumeratorT[B, F] {
def apply[A] = (step: StepT[B, F, A]) => {
def check(s: StepT[E, F, B]): IterateeT[B, F, A] = s.fold(
cont = k => k(eofInput) >>== {
s => s.mapContOr(_ => sys.error("diverging iteratee"), check(s))
}
, done = (a, _) => step.mapCont(f => f(elInput(a)))
)
iterateeT(M.bind((IterateeT.fold[E, F, B](b)(f) &= self).value) { s => check(s).value })
}
}
def cross[E2](e2: EnumeratorT[E2, F])(implicit M: Monad[F]): EnumeratorT[(E, E2), F] =
EnumerateeT.cross[E, E2, F](e2) run self
}
trait EnumeratorTInstances0 {
implicit def enumeratorTSemigroup[E, F[_]](implicit F0: Bind[F]): Semigroup[EnumeratorT[E, F]] =
new EnumeratorTSemigroup[E, F] {
implicit def F = F0
}
}
trait EnumeratorTInstances extends EnumeratorTInstances0 {
implicit def enumeratorTMonoid[E, F[_]](implicit F0: Monad[F]): Monoid[EnumeratorT[E, F]] =
new EnumeratorTMonoid[E, F] {
implicit def F = F0
}
implicit def enumeratorTMonad[F[_]](implicit M0: Monad[F]): Monad[EnumeratorT[*, F]] =
new EnumeratorTMonad[F] {
implicit def M = M0
}
implicit val enumeratorTMonadTrans: MonadTrans[({type l[β[_], α] = EnumeratorT[α, β]})#l] =
new MonadTrans[({type l[β[_], α] = EnumeratorT[α, β]})#l] {
def liftM[G[_]: Monad, E](ga: G[E]): EnumeratorT[E, G] =
new EnumeratorT[E, G] {
def apply[A] = (s: StepT[E, G, A]) => iterateeT(Monad[G].bind(ga) { e => s.mapCont(k => k(elInput(e))).value })
}
implicit def apply[G[_]: Monad]: Monad[EnumeratorT[*, G]] = enumeratorTMonad[G]
}
}
trait EnumeratorTFunctions {
def enumerate[E](as: Stream[E]): Enumerator[E] = enumStream[E, Id](as)
def empty[E, F[_]: Applicative]: EnumeratorT[E, F] =
new EnumeratorT[E, F] {
def apply[A] = _.pointI
}
/**
* An EnumeratorT that is at EOF
*/
def enumEofT[E, F[_] : Applicative]: EnumeratorT[E, F] =
new EnumeratorT[E, F] {
def apply[A] = _.mapCont(_(eofInput))
}
/**
* An enumerator that forces the evaluation of an effect in the F monad when it is consumed.
*/
def perform[E, F[_]: Monad, B](f: F[B]): EnumeratorT[E, F] =
new EnumeratorT[E, F] {
def apply[A] = s => iterateeT(Monad[F].bind(f) { _ => s.pointI.value })
}
def enumOne[E, F[_]: Applicative](e: E): EnumeratorT[E, F] =
new EnumeratorT[E, F] {
def apply[A] = _.mapCont(_(elInput(e)))
}
def enumStream[E, F[_] : Monad](xs: Stream[E]): EnumeratorT[E, F] =
new EnumeratorT[E, F] {
def apply[A] = (s: StepT[E, F, A]) => xs match {
case h #:: t => s.mapCont(k => k(elInput(h)) >>== enumStream[E, F](t).apply[A])
case _ => s.pointI
}
}
def enumList[E, F[_] : Monad](xs: List[E]): EnumeratorT[E, F] =
new EnumeratorT[E, F] {
def apply[A] = (s: StepT[E, F, A]) => xs match {
case h :: t => s.mapCont(k => k(elInput(h)) >>== enumList[E, F](t).apply[A])
case Nil => s.pointI
}
}
def enumIterator[E, F[_]](x: => Iterator[E])(implicit F: MonadIO[F]) : EnumeratorT[E, F] =
new EnumeratorT[E, F] {
def apply[A] = {
def go(xs: Iterator[E])(s: StepT[E, F, A]): IterateeT[E, F, A] =
if(xs.isEmpty) s.pointI
else {
s mapCont { k =>
val next = xs.next()
k(elInput(next)) >>== go(xs)
}
}
go(x)
}
}
def enumIoSource[T, E, F[_]](get : () => IoExceptionOr[T], gotdata : IoExceptionOr[T] => Boolean, render : T => E)(implicit F: MonadIO[F]): EnumeratorT[IoExceptionOr[E], F] =
new EnumeratorT[IoExceptionOr[E], F] {
def apply[A] = (s: StepT[IoExceptionOr[E], F, A]) =>
s.mapCont(
k => {
val i = get()
if (gotdata(i)) k(elInput(i.map(render))) >>== apply[A]
else s.pointI
}
)
}
def enumReader[F[_]](r: => java.io.Reader)(implicit F: MonadIO[F]): EnumeratorT[IoExceptionOr[Char], F] = {
lazy val src = r
enumIoSource(get = () => IoExceptionOr(src.read),
gotdata = (i: IoExceptionOr[Int]) => i exists (_ != -1),
render = ((n: Int) => n.toChar))
}
def enumInputStream[F[_]](is: => java.io.InputStream)(implicit F: MonadIO[F]): EnumeratorT[IoExceptionOr[Byte], F] = {
lazy val src = is
enumIoSource(get = () => IoExceptionOr(src.read),
gotdata = (i: IoExceptionOr[Int]) => i exists (_ != -1),
render = ((n:Int) => n.toByte))
}
def enumIndexedSeq[E, F[_]: Monad](a : IndexedSeq[E], min: Int = 0, max: Option[Int] = None) : EnumeratorT[E, F] =
new EnumeratorT[E, F] {
private[this] val limit = max.map(_ min (a.length)).getOrElse(a.length)
def apply[A] = {
def loop(pos : Int): StepT[E, F, A] => IterateeT[E, F, A] = {
s =>
s.mapCont(
k => if (limit > pos) k(elInput(a(pos))) >>== loop(pos + 1)
else s.pointI
)
}
loop(min)
}
}
/**
* An enumerator that yields the elements of the specified array from index min (inclusive) to max (exclusive)
*/
def enumArray[E, F[_]: Monad](a : Array[E], min: Int = 0, max: Option[Int] = None) : EnumeratorT[E, F] =
enumIndexedSeq(a, min, max)
def repeat[E, F[_] : Monad](e: E): EnumeratorT[E, F] =
new EnumeratorT[E, F] {
def apply[A] = (s: StepT[E, F, A]) => s.mapCont(_(elInput(e)) >>== apply[A])
}
def iterate[E, F[_] : Monad](f: E => E, e: E): EnumeratorT[E, F] =
new EnumeratorT[E, F] {
def apply[A]: StepT[E, F, A] => IterateeT[E, F, A] = {
type StepM = StepT[E, F, A]
type IterateeM = IterateeT[E, F, A]
def checkCont1(z: (E => (StepM => IterateeM)) => E => (Input[E] => IterateeM) => IterateeM, lastState: E): (StepM => IterateeM) = {
def step: E => (StepM => IterateeM) = {
state => _.mapCont(k => z(step)(state)(k))
}
step(lastState)
}
checkCont1(contFactory => state => k => k(elInput(e)) >>== contFactory(f(state)), e)
}
}
}
// Instances are mixed in with the IterateeT object
object EnumeratorT extends EnumeratorTFunctions with EnumeratorTInstances
//
// Type class implementation traits
//
private trait EnumeratorTSemigroup[E, F[_]] extends Semigroup[EnumeratorT[E, F]] {
implicit def F: Bind[F]
def append(f1: EnumeratorT[E, F], f2: => EnumeratorT[E, F]) =
new EnumeratorT[E, F] {
def apply[A] = (s: StepT[E, F, A]) => f1[A](s) >>== f2[A]
}
}
private trait EnumeratorTMonoid[E, F[_]] extends Monoid[EnumeratorT[E, F]] with EnumeratorTSemigroup[E, F] {
implicit def F: Monad[F]
def zero = new EnumeratorT[E, F] {
def apply[A] = (s: StepT[E, F, A]) => s.pointI
}
}
private trait EnumeratorTFunctor[F[_]] extends Functor[EnumeratorT[*, F]] {
implicit def M: Monad[F]
abstract override def map[A, B](fa: EnumeratorT[A, F])(f: A => B): EnumeratorT[B, F] = fa.map(f)
}
private trait EnumeratorTMonad[F[_]] extends Monad[EnumeratorT[*, F]] with EnumeratorTFunctor[F] {
def bind[A, B](fa: EnumeratorT[A, F])(f: A => EnumeratorT[B, F]) = fa.flatMap(f)
def point[E](e: => E) = EnumeratorT.enumOne[E, F](e)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy