/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

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