使用 Monads Transformer 堆叠 Monads

Stacking Monads using Monads Transformers

我正在学习 Monad Transformers,我正在尝试学习如何嵌套 Monad。

假设我想创建一个 Future[Either[String, Option[A]]]

所以为了模拟这个形状我做了

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

现在我做

val p1 = 1.pure[FutureEitherOption]

我得到

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

所以这看起来是正确的。我在一个 Option 里面有一个 1,它在一个 Right 里面,它在一个 Future Success 里面。好!

但如果我这样做

Option.empty[Int].pure[FutureEitherOption]

我希望我能得到 Future(Success(Right(None))) 但我看到了输出

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

此外,如果我想要类似

的东西
Future(Success(Left("fail")))

如果我尝试做

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

输出很奇怪

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

那根本不是我的形状,因为现在有两个 Eithers....

1Int 类型,因此通过调用 .pure[FutureEitherOption] 你会得到正确的形状:

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

Option.empty[Int] 是类型 Option[Int] 所以你需要做:

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

为了获得正确的形状:

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

Left("fail")Left[String, Nothing] 类型(但实际上也是 Either[Error, Option[Int]])所以你需要做:

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

为了获得正确的形状:

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

然后你终于可以编写所有这些了。例如,您可以将 for-comprehension 写为:

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 ()

注意:我已经明确注释了所有类型,以便您更好地理解它是怎么回事。