PageRenderTime 22ms CodeModel.GetById 7ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/core/src/main/scala/scalaz/Monad.scala

http://github.com/scalaz/scalaz
Scala | 109 lines | 48 code | 17 blank | 44 comment | 4 complexity | c3508c9eef16e0feddb0c35c240e77cb MD5 | raw file
  1package scalaz
  2
  3////
  4/**
  5 * Monad, an [[scalaz.Applicative]] that also supports [[scalaz.Bind]],
  6 * circumscribed by the monad laws.
  7 *
  8 * @see [[scalaz.Monad.MonadLaw]]
  9 */
 10////
 11trait Monad[F[_]] extends Applicative[F] with Bind[F] { self =>
 12  ////
 13
 14  override def map[A,B](fa: F[A])(f: A => B) = bind(fa)(a => point(f(a)))
 15
 16  /**
 17   * Execute an action repeatedly as long as the given `Boolean` expression
 18   * returns `true`. The condition is evaluated before the loop body.
 19   * Collects the results into an arbitrary `MonadPlus` value, such as a `List`.
 20   */
 21  def whileM[G[_], A](p: F[Boolean], body: => F[A])(implicit G: MonadPlus[G]): F[G[A]] = {
 22    val f = Need(body)
 23    ifM(p, bind(f.value)(x => map(whileM(p, f.value))(xs => G.plus(G.point(x), xs))), point(G.empty))
 24  }
 25
 26  /**
 27   * Execute an action repeatedly as long as the given `Boolean` expression
 28   * returns `true`. The condition is evaluated before the loop body.
 29   * Discards results.
 30   */
 31  def whileM_[A](p: F[Boolean], body: => F[A]): F[Unit] = {
 32    val f = Need(body)
 33    ifM(p, bind(f.value)(_ => whileM_(p, f.value)), point(()))
 34  }
 35
 36  /**
 37   * Execute an action repeatedly until the `Boolean` condition returns `true`.
 38   * The condition is evaluated after the loop body. Collects results into an
 39   * arbitrary `MonadPlus` value, such as a `List`.
 40   */
 41  def untilM[G[_], A](f: F[A], cond: => F[Boolean])(implicit G: MonadPlus[G]): F[G[A]] = {
 42    val p = Need(cond)
 43    bind(f)(x => map(whileM(map(p.value)(!_), f))(xs => G.plus(G.point(x), xs)))
 44  }
 45
 46  /**
 47   * Execute an action repeatedly until the `Boolean` condition returns `true`.
 48   * The condition is evaluated after the loop body. Discards results.
 49   */
 50  def untilM_[A](f: F[A], cond: => F[Boolean]): F[Unit] = {
 51    val p = Need(cond)
 52    bind(f)(_ => whileM_(map(p.value)(!_), f))
 53  }
 54
 55  /**
 56   * Execute an action repeatedly until its result fails to satisfy the given predicate
 57   * and return that result, discarding all others.
 58   */
 59  def iterateWhile[A](f: F[A])(p: A => Boolean): F[A] =
 60    bind(f)(y => if (p(y)) iterateWhile(f)(p) else point(y))
 61
 62  /**
 63   * Execute an action repeatedly until its result satisfies the given predicate
 64   * and return that result, discarding all others.
 65   */
 66  def iterateUntil[A](f: F[A])(p: A => Boolean): F[A] =
 67    bind(f)(y => if (p(y)) point(y) else iterateUntil(f)(p))
 68
 69  /**The product of Monad `F` and `G`, `[x](F[x], G[x]])`, is a Monad */
 70  def product[G[_]](implicit G0: Monad[G]): Monad[λ[α => (F[α], G[α])]] =
 71    new ProductMonad[F, G] {
 72      def F = self
 73      def G = G0
 74    }
 75
 76  trait MonadLaw extends ApplicativeLaw with BindLaw {
 77    /** Lifted `point` is a no-op. */
 78    def rightIdentity[A](a: F[A])(implicit FA: Equal[F[A]]): Boolean = FA.equal(bind(a)(point(_: A)), a)
 79    /** Lifted `f` applied to pure `a` is just `f(a)`. */
 80    def leftIdentity[A, B](a: A, f: A => F[B])(implicit FB: Equal[F[B]]): Boolean = FB.equal(bind(point(a))(f), f(a))
 81  }
 82  def monadLaw = new MonadLaw {}
 83  ////
 84  val monadSyntax: scalaz.syntax.MonadSyntax[F] =
 85    new scalaz.syntax.MonadSyntax[F] { def F = Monad.this }
 86}
 87
 88object Monad {
 89  @inline def apply[F[_]](implicit F: Monad[F]): Monad[F] = F
 90
 91  import Isomorphism._
 92
 93  def fromIso[F[_], G[_]](D: F <~> G)(implicit E: Monad[G]): Monad[F] =
 94    new IsomorphismMonad[F, G] {
 95      override def G: Monad[G] = E
 96      override def iso: F <~> G = D
 97    }
 98
 99  ////
100
101  ////
102}
103
104trait IsomorphismMonad[F[_], G[_]] extends Monad[F] with IsomorphismApplicative[F, G] with IsomorphismBind[F, G]{
105  implicit def G: Monad[G]
106  ////
107
108  ////
109}