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

scalaz.MonadTell.scala Maven / Gradle / Ivy

package scalaz

////
/** The class of monads supporting write operations
 *
 */
////
trait MonadTell[F[_], S] extends Monad[F] { self =>
  ////
  def writer[A](w: S, v: A): F[A]

  def tell(w: S): F[Unit] = writer(w, ())

  ////
  val monadTellSyntax: scalaz.syntax.MonadTellSyntax[F, S] =
    new scalaz.syntax.MonadTellSyntax[F, S] { def F = MonadTell.this }
}

object MonadTell {
  @inline def apply[F[_], S](implicit F: MonadTell[F, S]): MonadTell[F, S] = F

  import Isomorphism._

  def fromIso[F[_], G[_], E](D: F <~> G)(implicit A: MonadTell[G, E]): MonadTell[F, E] =
    new IsomorphismMonadTell[F, G, E] {
      override def G: MonadTell[G, E] = A
      override def iso: F <~> G = D
    }

  ////
  /** The Free instruction set for MonadTell */
  sealed abstract class Ast[S, A]
  final case class Writer[S, A](s: S, a: A) extends Ast[S, A]

  /** Extensible Effect */
  def liftF[F[_], S](
    implicit I: Ast[S, *] :<: F
  ): MonadTell[Free[F, *], S] & BindRec[Free[F, *]] =
    new MonadTell[Free[F, *], S] with BindRec[Free[F, *]] {
      val delegate = Free.freeMonad[F]
      def point[A](a: =>A): Free[F, A] = delegate.point(a)
      def bind[A, B](fa: Free[F, A])(f: A => Free[F, B]) = delegate.bind(fa)(f)
      override def map[A, B](fa: Free[F, A])(f: A => B) = delegate.map(fa)(f)

      def tailrecM[A, B](a: A)(f: A => Free[F, A \/ B]) = delegate.tailrecM(a)(f)

      def writer[A](w: S, v: A): Free[F, A] = Free.liftF(I.inj(Writer[S, A](w, v)))
    }
  ////
}

trait IsomorphismMonadTell[F[_], G[_], S] extends MonadTell[F, S] with IsomorphismMonad[F, G]{
  implicit def G: MonadTell[G, S]
  ////

  override def writer[A](w: S, v: A): F[A] =
    iso.from(G.writer(w, v))
  ////
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy