1

假设您有一个看起来像这样的 EitherT:

type StateListOfString[+T] = State[List[String], T]
type MyEitherT = EitherT[StateListOfString, Int, Boolean]

如果您有一个可以返回左的理解:

my computation = for {
  a <- thingThatCouldReturnLeft
  b <- otherThingThatCouldReturnLeft
} yield b

你如何跟进一个在自身返回左侧之前操纵状态的理解?

我想我想要一些非常接近 orElse 的东西,但是 orElse 无法访问左侧的值:

  def orElse[AA >: A, BB >: B](x: => EitherT[F, AA, BB])(implicit F: Bind[F]): EitherT[F, AA, BB] = {

如果它需要像 (x: => Int => EitherT[F, AA, BB]) 而不是仅仅 (x: => EitherT[F, AA, BB]),它会起作用。

我曾尝试从:

for {
  a <- myComputation.isLeft
  // OK, now I have something sensible, and I can follow up with something like
  // a leftMap

但是如果我从调用 isLeft 开始,看起来计算至少运行了两次,一次是为 isLeft,一次是在我调用 leftMap 之类的东西时。

在这里使用什么是正确的?

4

1 回答 1

1

查看它的来源orElse似乎可以自然地概括为

import scala.language.higherKinds

def onLeft[F[+_],A,B](x: => EitherT[F, A, B])
                     (y: A => EitherT[F, A, B])
                     (implicit F: Bind[F]): EitherT[F, A, B] =
{
  val g = x.run
  EitherT(F.bind(g) {
    case -\/(l) => y(l).run
    case \/-(_) => g
  })
}

这基本上与交换左/右然后使用单子绑定相同

def onLeft1[F[+_],A,B](x: => EitherT[F, A, B])
                      (y: A => EitherT[F, A, B])
                      (implicit F: Monad[F]): EitherT[F, A, B] =
  x.swap.flatMap((a: A) => y(a).swap).swap

但当然第一个变体更有效(并且在 中也更通用F)。

于 2013-07-14T10:20:55.170 回答