0

I'm planning to use Bifunctor IO with a channel for errors. So I tried to provide an implicit instance for MonadError but it fails to compile.

import cats.MonadError

sealed trait AppErrors
   //...

object App{
    def runApp[F[_, _]: MonadError[F[AppErrors, ?], ?]] = {

    }
}

For instance cats-bio: cats.BIO[+E, +A]

I got the compile error

Error:(13, 22) type F takes type parameters
  def runApp[F[_, _] : MonadError[F[AppErrors, ?], ?]] ={}

I do not really understand how to fix that requiring MonadError[F[_], A].

St.Antario
  • 26,175
  • 41
  • 130
  • 318
  • 2
    Unclear what you attempted there. If you had some typeclass `trait Typeclass[B[_, _]] { ... }`, then you could write `def foo[F[_, _]: Typeclass]`, because the type constructor `Typeclass` would take a single argument of kind `(*,*) -> *`. But your `MonadError[F[... ? ... ?]]`-contraption seems to take two arguments, both of kind `*`. How is that supposed to fit together? And also: `F: BlahBlah[F]` looks self-referential. – Andrey Tyukin Feb 17 '19 at 14:22
  • @AndreyTyukin Would it make sense to parameterize method as `def runApp[F[_]: MonadError[?, AppError]]` and later on define `F := BIO[AppErrors, ?]`? – St.Antario Feb 17 '19 at 14:26
  • That looks as if it had better chances to compile, at least on the first glance. I somehow cannot find who or what would provide an instance of `MonadError[BIO[AppError, ?], AppError]`. But at least I found lots of links to suppliers of organic cat food :] – Andrey Tyukin Feb 17 '19 at 14:53
  • 1
    @AndreyTyukin _who or what would provide an instance_ But what's a problem with that? `BIO[E, A]` has `Bracket` instance so either does `MonadError`. – St.Antario Feb 17 '19 at 14:56
  • Ok, then it provides Bracket. What's the problem with `def runApp[F[_]: MonadError[?, AppError]]` and `Bracket` implementing `MonadError[BIO[AppError, ?], AppError]` then? It seems that you've answered your own question yourself. Or maybe consider updating the question with the type constructors that fit together kind-wise, and then explaining why it still doesn't do what you want. – Andrey Tyukin Feb 17 '19 at 15:03
  • @AndreyTyukin The problem I could see is that the errors would be represented as ADT. Even if I know that some method of `trait Typeclass[B[_, _]]{ ... }` can raise only one specific error (of 10 (say) branches of `AppErrors`) in order to `handleError` I would have to pattern-match against all the branches. Does not it feel like some mess? – St.Antario Feb 17 '19 at 15:07
  • 2
    I'm not sure why you are still talking about `(*,*) -> *`-kinded typeclasses: both `MonadError[?, E]` and `BIO[E, ?]` are `*->*`. I also cannot comment on the variances of all those type constructors right now. But I think that the question is getting increasingly out-of-sync with the comments, because it still has the `F[_, _]` in it? – Andrey Tyukin Feb 17 '19 at 15:16
  • 2
    I believe you are using kind-projector sbt plugin. I had similar issue and solved it by using both ? and _ . For example: `def runApp[F[_, _]](implicit ev: MonadError[F[AppErrors, ?], _])` – Alexey Novakov Feb 17 '19 at 22:08
  • @AlexeyNovakov but is there a way to provide it in the form `[A: Typeclass]`? Currently I think it is not... – St.Antario Feb 18 '19 at 07:31
  • 1
    @St.Antario I am not sure, whether context boundary will work here. I could compile your code having cats in sbt deps with scala 2.12, kind-projector plugin. Though I can't see any other problem. Perhaps, you could give more details, so that we could reproduce your compile error. – Alexey Novakov Feb 18 '19 at 07:48

0 Answers0