Search code examples
scalascala-cats

Why does scala not infer the right type when wrapping EitherT?


Here's the code:

// eventually will be an implicit class with extension methods
class EitherTWrapper [L,R] (ei: EitherT[Future,L,R])

new EitherTWrapper(??? : EitherT[Future,Nothing,Boolean])

Fails to compile with:

type mismatch;
 found   : cats.data.EitherT[scala.concurrent.Future,Nothing,Boolean]
 required: cats.data.EitherT[scala.concurrent.Future,L,Boolean]
Note: Nothing <: L, but class EitherT is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)

It works fine if I provide the types explicitly, like this:

new EitherTWrapper[Nothing,Boolean](??? : EitherT[Future,Nothing,Boolean])

Which would work, except that I can't do that if I'm trying to make it an implicit class.

I expected this to work. How do I define a class that can wrap an EitherT?


Solution

  • Apparently, it's a known scala compiler bug (limitation?): https://github.com/scala/bug/issues/9453

    It seems there's 2 workarounds:

    • Make the type covariant on the wrapper (not great because now the wrapper has a different variance behavior than the thing being wrapped and only works if the type param is not being used contravariantly).
    • Treat the version of EitherT with Nothing specially, by creating a separate wrapper for it. This works even when trying to use the wrappers as implicit classes.