Knows Not Much
Knows Not Much

Reputation: 31556

Stacking Monads using Monads Transformers

I am learning Monad Transformers and I am trying to learn how to nest Monads.

So let's say I want to create a Future[Either[String, Option[A]]]

So in order to model this shape I did

type Error = String
type FutureEither = EitherT[Future, Error, A]
type FutureEitherOption = OptionT[FutureEither, A]

Now I do

val p1 = 1.pure[FutureEitherOption]

and I get

OptionT(EitherT(Future(Success(Right(Some(1))))))

So this looks correct. I have a 1 inside of an Option which is inside of a Right, Which is inside of a Future Success. Good!

But If I do

Option.empty[Int].pure[FutureEitherOption]

I was hoping that I will get Future(Success(Right(None))) but I see output

OptionT(EitherT(Future(Success(Right(Some(None))))))

Also, If I want something like

Future(Success(Left("fail")))

If i try to do

val p2 = Left("fail").pure[FutureEitherOption]

The output is weird

OptionT(EitherT(Future(Success(Right(Some(Left(fail)))))))

That's not my shape at all because now there are two Eithers....

Upvotes: 2

Views: 145

Answers (1)

Federico Pellegatta
Federico Pellegatta

Reputation: 4017

1 is of type Int and so by calling .pure[FutureEitherOption] you get the right shape:

OptionT(EitherT(Success(Right(Some(1)))))

Option.empty[Int] is of type Option[Int] so you need to do:

OptionT[FutureEither, Int](Option.empty[Int].pure[FutureEither])

in order to get the the right shape:

OptionT(EitherT(Success(Right(None))))

Left("fail") is of type Left[String, Nothing] (but actually also Either[Error, Option[Int]]) so you need to do:

OptionT[FutureEither, Int](EitherT[Future, Error, Option[Int]](Either.left[Error, Option[Int]]("fail").pure[Future]))

in order to get the the right shape:

OptionT(EitherT(Success(Left(fail))))

Then you can finally compose all of those. For example you can write a for-comprehension as:

for {
  a <- 1.pure[FutureEitherOption]
  b <- OptionT[FutureEither, Int](Option.empty[Int].pure[FutureEither])
  c <- OptionT[FutureEither, Int](EitherT[Future, Error, Option[Int]](Either.left[Error, Option[Int]]("fail").pure[Future]))
} yield ()

Note: I have explicitly annotated all types in order to let you better understand what its going on.

Upvotes: 3

Related Questions