Cats-MTL v0.7.1 allows both arrangements.
Cats-MTL v1.1.1 case works only when EitherT is on the top.
Using: cats-mtl v0.7.1
https://scastie.scala-lang.org/vIEWTZkrTlGyel2jBiwRoA
import cats.{Monad, Id}
import cats.data.{StateT, EitherT}
import cats.implicits._
import cats.mtl.{MonadState, FunctorRaise}
import cats.mtl.implicits._
object Main extends App {
def computation[F[_]: Monad: MonadState[*[_], Int]: FunctorRaise[*[_], String]](a: Int): F[Int] = a.pure[F]
type MyEither[A] = EitherT[Id, String, A]
type MyState[A] = StateT[MyEither, Int, A]
val result = computation[MyState](42).run(0).value // <====== NO ERROR
println(result)
}
Using: cats-mtl v1.1.1
https://scastie.scala-lang.org/bZE05pflSnKOjpPiGmksjg
import cats.{Monad, Id}
import cats.data.{StateT, EitherT}
import cats.implicits._
import cats.mtl.{Stateful, Raise}
import cats.mtl.implicits._
object Main extends App {
def computation[F[_]: Monad: Stateful[*[_], Int]: Raise[*[_], String]](a: Int): F[Int] = a.pure[F]
type MyEither[A] = EitherT[Id, String, A]
type MyState[A] = StateT[MyEither, Int, A]
val result = computation[MyState](42).run(0).value // <====== ERROR
println(result)
}
Compiler output
Details
Could not find an implicit instance of Raise[Main.MyState, String]. If you have
a good way of handling errors of type String at this location, you may want
to construct a value of type EitherT for this call-site, rather than Main.MyState.
An example type:
EitherT[Main.MyState, String, *]
This is analogous to writing try/catch around this call. The EitherT will
"catch" the errors of type String.
If you do not wish to handle errors of type String at this location, you should
add an implicit parameter of this type to your function. For example:
(implicit fraise: Raise[Main.MyState, String])
Manually defining the missing Raise instance using def raise(e) = StateT.liftF(EitherT.leftT(e)) makes it work.
Cats-MTL v0.7.1 allows both arrangements.
Cats-MTL v1.1.1 case works only when EitherT is on the top.
Using: cats-mtl v0.7.1
https://scastie.scala-lang.org/vIEWTZkrTlGyel2jBiwRoA
Using: cats-mtl v1.1.1
https://scastie.scala-lang.org/bZE05pflSnKOjpPiGmksjg
Compiler output
Details
Manually defining the missing
Raiseinstance usingdef raise(e) = StateT.liftF(EitherT.leftT(e))makes it work.