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

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

There is a newer version: 7.3.3
Show newest version
package scalaz
package iteratee

import LazyOption._
import Iteratee._

/**The input to an iteratee. **/
sealed abstract class Input[E] {

  def fold[Z](empty: => Z, el: (=> E) => Z, eof: => Z): Z

  def apply[Z](empty: => Z, el: (=> E) => Z, eof: => Z): Z =
    fold(empty, el, eof)

  def el: LazyOption[E] =
    apply(lazyNone[E], lazySome(_), lazyNone[E])

  def elOr(e: => E): E =
    el.getOrElse(e)

  def isEmpty: Boolean =
    apply(true, _ => false, false)

  def isEl: Boolean =
    apply(false, _ => true, false)

  def isEof: Boolean =
    apply(false, _ => false, true)

  def map[X](f: (=> E) => X): Input[X] =
    fold(emptyInput, e => elInput(f(e)), eofInput)

  def flatMap[X](f: (=> E) => Input[X]): Input[X] =
    fold(emptyInput, e => f(e), eofInput)

  def filter(f: (=> E) => Boolean): Input[E] =
    fold(emptyInput, e => if (f(e)) this else emptyInput, eofInput)

  def foreach(f: (=> E) => Unit): Unit =
    fold((), e => f(e), ())

  def forall(p: (=> E) => Boolean): Boolean =
    fold(true, p, true)

  def exists(p: (=> E) => Boolean): Boolean =
    fold(false, p, false)

  override final def toString = fold("Empty", el => el.toString, "EOF")
}

object Input extends InputInstances with InputFunctions {
  def apply[E](e: => E): Input[E] =
    elInput(e)

  object Empty {
    def apply[E]: Input[E] = new Input[E] {
      def fold[Z](empty: => Z, el: (=> E) => Z, eof: => Z) = empty
    }

    def unapply[E](i: Input[E]): Boolean = i.fold(true, _ => false, false)
  }


  object Element {
    def apply[E](e: => E): Input[E] = new Input[E] {
      def fold[Z](empty: => Z, el: (=> E) => Z, eof: => Z) = el(e)
    }

    def unapply[E](i: Input[E]): Option[E] = i.fold(None, Some(_), None)
  }

  object Eof {
    def apply[E]: Input[E] = new Input[E] {
      def fold[Z](empty: => Z, el: (=> E) => Z, eof: => Z) = eof
    }

    def unapply[E](i: Input[E]): Boolean = i.fold(false, _ => false, true)
  }

}

sealed abstract class InputInstances {
  import Input._

  implicit val input: Traverse[Input] with Monad[Input] with Plus[Input] = new Traverse[Input] with Monad[Input] with Plus[Input] {
     override def length[A](fa: Input[A]): Int = fa.fold(
       empty = 0
       , el = _ => 1
       , eof = 0
     )
     def point[A](a: => A): Input[A] = elInput(a)
     def traverseImpl[G[_]: Applicative, A, B](fa: Input[A])(f: A => G[B]): G[Input[B]] = fa.fold(
       empty = Applicative[G].point(emptyInput[B])
       , el = x => Applicative[G].map(f(x))(b => elInput(b))
       , eof = Applicative[G].point(eofInput[B])
     )
    override def foldRight[A, B](fa: Input[A], z: => B)(f: (A, => B) => B): B = fa.fold(
       empty = z
       , el = a => f(a, z)
       , eof = z
     )
     def plus[A](a: Input[A], b: => Input[A]): Input[A] = a.fold(
       empty = b
       , el = _ => a
       , eof = b
     )
     def bind[A, B](fa: Input[A])(f: A => Input[B]): Input[B] = fa flatMap (a => f(a))
   }

   implicit def inputSemigroup[A](implicit A: Semigroup[A]): Semigroup[Input[A]] = new Semigroup[Input[A]] {
     def append(a1: Input[A], a2: => Input[A]): Input[A] = a1.fold(
       empty = a2.fold(
         empty = emptyInput
         , el = elInput
         , eof = eofInput
       )
       , el = xa => a2.fold(
         empty = elInput(xa)
         , el = ya => elInput(A.append(xa, ya))
         , eof = eofInput
       )
       , eof = eofInput
     )
   }

   implicit def inputEqual[A](implicit A: Equal[A]): Equal[Input[A]] = new Equal[Input[A]] {
     def equal(a1: Input[A], a2: Input[A]): Boolean = a1.fold(
       empty = a2.isEmpty
       , el = a => a2.exists(z => A.equal(a, z))
       , eof = a2.isEof
     )
   }

  implicit def inputShow[A](implicit A: Show[A]): Show[Input[A]] = Show.show { i =>
    import scalaz.syntax.show._
    i.fold(
      empty = Cord("empty-input"),
      el = a => cord"el-input($a)",
      eof = Cord("eof-input")
    )
  }
}

trait InputFunctions {
  def emptyInput[E]: Input[E] = Input.Empty[E]
  def elInput[E](e: => E): Input[E] = Input.Element(e)
  def eofInput[E]: Input[E] = Input.Eof[E]
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy