I often do things like:
import cats.effect.Sync
import cats.implicits._
case class User(name: String)
case object Error extends Exception
def validate[F[_]: Sync](name: String): F[Either[Error, User]] = Sync[F].pure(User(name).asRight)
def doSomething[F[_]: Sync]: F[User] = for {
maybeUser <- validate("Name")
user <- maybeUser.fold(Sync[F].raiseError[User](_), Sync[F].pure(_))
} yield user
In nutshell, it means if Either
is left
then use raiseError
, if it's right
just return value.
Is there a more convenient way to "unwrap" Either
?
Use liftTo
from the cats Either
syntax: maybeUser.liftTo[F]
.
You can also use rethrow
, from the cats MonadError
syntax, directly on F[Either[Error, User]]
:
def doSomething[F[_]: Sync]: F[User] = validate[F]("Name").rethrow
Note that you don't actually need Sync
- MonadError[*[_], Throwable]
is sufficient.