type ErrorOr[A] = Either[Error, A]
type _option[R] = Option |= R
type _io[R] = |=[IO, R]
type _errorOr[R] = ErrorOr |= R
def program[R :_io :_option :_errorOr]
(userId: String, teamName: String): Eff[R, Response] =
for {
userOpt user team _ } yield createResponse(user, team)
MTL Eff
type Stack = Fx.fx3[Option, ErrorOr, IO]
program[Stack](userId, teamName)
.runOption // Eff[Fx2[Either, IO], Option[Response]]
.runEither[Error] // Eff[Fx1[IO], Either[Error, Option[Response]]
.to[IO] // IO[Either[Error, Option[Response]]]
program(userId, teamName) // OptionT[EitherIO, Response]
.value // EitherT[IO, Error, Option[Response]]
.value // IO[Either[Error, Option[Response]]]
type EitherIO[A] = EitherT[IO, Error, A]
def program(userId: String, teamName: String):
OptionT[EitherIO, Response] = {
for {
user (EitherT.liftF[IO, Error, Option[User]](findUser(userId)))
team (EitherT.fromEither[IO](createTeam(userId, teamName)))
_ (EitherT.liftF[IO, Error, Unit](storeTeam(team)))
} yield createResponse(user, team)
}
MTL vs atnos-eff
41