How to fold ReaderT and WriterT converters into a scalar?

I play with monad transformers in scalaz. I am trying to put Writer together at the top of the Reader with the main monad Id. To combine them, I use classes like MonadReaderand MonadWriter.

I managed to compile and run the following code example without an author (i.e. with a monad Reader, i.e. ReaderT[Id.Id, String, A]). When added WriterTto the stack, I get a compilation error:

Gist.scala:10: could not find implicit value for parameter F: scalaz.MonadReader[Gist.R,String]
   val MR = MonadReader[R, String]
                       ^

How can I get an instance MonadReaderfor my transformer stack? Should I use ReaderWriterStateTor is there another way?

Full code:

import scalaz.{Id, MonadListen, MonadReader, ReaderT, WriterT}

object Gist {
  import scalaz.std.list._
  import scalaz.syntax.monad._

  type P[A] = ReaderT[Id.Id, String, A]
  type R[A] = WriterT[P, List[String], A]

  val MR = MonadReader[R, String]
  val MW = MonadListen[R, List[String]]

  def apply: R[String] = MR.ask >>= { greeting =>
    MW.tell(List(s"greeting $greeting")) >>= { _ =>
      MW.point(s"Hello $greeting")
    }
  }
}
+4
source share
1 answer

, Scalaz ( MonadReader ), , , WriterTInstanceN 11, MonadReader .

Scalaz GitHub ( IRC, ), , .

Haskell mtl:

instance (Monoid w, MonadReader r m) => MonadReader r (Strict.WriterT w m) where
    ask   = lift ask
    local = Strict.mapWriterT . local
    reader = lift . reader

Scala :

import scalaz.{ MonadReader, MonadTrans, Monoid, WriterT }
import scalaz.syntax.monad._

implicit def monadReaderForWriterT[F[_], I, W](implicit
  F: MonadReader[F, I],
  W: Monoid[W]
): MonadReader[WriterT[F, W, ?], I] = new MonadReader[WriterT[F, W, ?], I] {
  def ask: WriterT[F, W, I] = MonadTrans[WriterT[?[_], W, ?]].liftM(F.ask)

  def local[A](f: I => I)(fa: WriterT[F, W, A]): WriterT[F, W, A] =
    fa.mapT(F.local(f))

  def point[A](a: => A): WriterT[F, W, A] = a.point[WriterT[F, W, ?]]
  def bind[A, B](fa: WriterT[F, W, A])(
    f: A => WriterT[F, W, B]
  ): WriterT[F, W, B] = fa.flatMap(f)
}

, kind-projector, , Haskell .

, :

import scalaz.{ Id, MonadListen, ReaderT }
import scalaz.std.list._

type P[A] = ReaderT[Id.Id, String, A]
type R[A] = WriterT[P, List[String], A]

val MR = MonadReader[R, String]
val MW = MonadListen[R, List[String]]

def apply: R[String] = MR.ask >>= { greeting =>
  MW.tell(List(s"greeting $greeting")) >>= { _ =>
    MW.point(s"Hello $greeting")
  }
}
+5

Source: https://habr.com/ru/post/1674538/


All Articles