Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FunctorListen doesn't understand nested Monad stack #180

Open
thobson opened this issue Jan 13, 2020 · 0 comments
Open

FunctorListen doesn't understand nested Monad stack #180

thobson opened this issue Jan 13, 2020 · 0 comments

Comments

@thobson
Copy link

thobson commented Jan 13, 2020

I'm trying to stack a WriterT and EitherT together - ultimately something like IO[Writer[Log, Either[Throwable, A]]]. The idea is that even in the event of an error the log up to that point should be maintained.

I have created a POC which uses a transformer stack of EitherT[WriterT[IO, Log, *], Throwable, *] and when I materialise the program it works as expected. The logs are present even in the event of an error. However FunctorListen seems to short circuit in the event of an error. Here is the code itself:

object POC extends IOApp {

  import cats.instances.vector._
  import cats.mtl.implicits._
  import cats.syntax.flatMap._
  import cats.syntax.functor._

  type Log = Vector[String]

  override def run(args: List[String]): IO[ExitCode] = {
    val name = getName[EitherT[WriterT[IO, Log, *], Throwable, *]]
    // this works even with a raised error so the stack itself is working
    name.value.written.flatTap(logs => IO(println(logs))).as(ExitCode.Success)
    // this won't work
    printLog(name).value.run.as(ExitCode.Success)
  }

  def printLog[F[_], A](fa: F[A])(implicit F: Sync[F], FL: FunctorListen[F, Log]): F[A] = {
    // this is never called when an error is raised
    fa.listen.flatMap { case (a, logs) => F.delay(println(logs)).as(a) }
  }

  def getName[F[_]](implicit F: Sync[F], FT: FunctorTell[F, Log], FR: FunctorRaise[F, Throwable]): F[String] = for {
    _ <- FT.tell(Vector("getting name ..."))
    a <- F.delay("bob")
    // Exception here means FunctorListen cant find any logs
    _ <- FR.raise(new Exception("boom!")): F[Unit]
  } yield a

}

I'm not sure if this is a problem with FunctorListen or FunctorRaise. It could be that FunctorRaise is raising an error at the IO level not the Either/EitherT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant