2

我正在学习 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))))))

所以这看起来是正确的。我在一个选项里面有一个 1,它在一个权利里面,它在一个未来的成功里面。好的!

但如果我这样做

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

那根本不是我的形状,因为现在有两个非他莫属......

4

1 回答 1

3

1是类型Int,所以通过调用.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 ()

注意:我已经明确地注释了所有类型,以便让您更好地理解它发生了什么。

于 2017-03-07T10:25:24.113 回答