I'm working on a small program using Scala Cats. I'm encountering lots of type errors when trying to use EitherT
with State
and for comprehensions. For instance:
import cats.data.{EitherT, State}
import cats.data.State.get
object Test {
type IntState[T] = State[Int, T]
type IntStateEither[T] = EitherT[IntState, String, T]
val test: IntStateEither[Unit] = for {
isValid <- EitherT.right(get.map((it: Int) => it % 2 == 0))
_ <- if (!isValid) EitherT.leftT("invalid number") else EitherT.rightT(()) // *
} yield ()
}
Which gives me:
(...) Test.scala:12: type mismatch;
found : cats.data.EitherT[[A(in value <local Id>)]A(in value <local Id>),_1,Unit] where type _1 <: String
required: cats.data.EitherT[[A(in class IndexedStateT)]cats.data.IndexedStateT[cats.Eval,Int,Int,A(in class IndexedStateT)],String,Unit]
one error found
If I comment out the line marked (*) above, this code compiles. I think I'm following the instructions on the Cats website under "From A
or B
to EitherT[F, A, B]
" correctly, but do I need to give more type hints? If yes, I'm not sure where I can add them.
Any pointers are greatly appreciated!
I'm using Cats 2.0.0 and Scala 2.13.2.
It seems that the problem is that the compiler is not able to infer the correct types for EitherT.leftT
and EitherT.rightT
.
You can fix those errors using explicit types like: EitherT.rightT[IntState, String]
, or if you only need one flatMap
call, it seems doing it explicitly does work:
val test: IntStateEither[Unit] =
EitherT
.right[String](State.get[Int].map(it => it % 2 == 0))
.flatMap { isValid =>
if (isValid) EitherT.rightT(())
else EitherT.leftT("invalid number")
}
PS: It may be worth checking if bm4 helps.