Scala 匹配运行计算的结果在中无效,以便理解

Scala 匹配运行计算的结果在中无效,以便理解,scala,monads,scala-cats,for-comprehension,Scala,Monads,Scala Cats,For Comprehension,我在一个理解的框架内,我们一起组成多个操作。当每个步骤完成时,我需要使用MonadError.raiseError抛出一个错误,或者继续执行下一步(如果有效) def myFunc[F[_]: Monad](input: Input)(implicit err: MonadError) = { for { stepAResult <- runStepA(input) if (stepAResult.isInstanceOf[Invalid[_]) { err

我在一个理解的框架内,我们一起组成多个操作。当每个步骤完成时,我需要使用
MonadError.raiseError
抛出一个错误,或者继续执行下一步(如果有效)

def myFunc[F[_]: Monad](input: Input)(implicit err: MonadError) = {
  for {
    stepAResult <- runStepA(input)
    if (stepAResult.isInstanceOf[Invalid[_]) {
      err.raiseError(new Throwable("error 1"))
    } else {
       stepBResult<- runStepB(stepAResult.toOption.get, input)
       if (stepBResult.isInstanceOf[Invalid[_]]) {
          err.raiseError(new Throwable("error 2"))
       } else {
        stepCResult <- runStepC(stepBResult.toOption.get)
        // check for invalid here again.
      }
    }
  }
}
def myFunc[F[\ux]:Monad](输入:输入)(隐式错误:MonadError)={
为了{

stepAResult假设您可以控制“runStep”函数,我建议您修改它们以返回一个[Invalid,u]或[Invalid],这样,您就可以将它们组合成一个单独的函数,以便理解(我使用了Throwable而不是Invalid,但想法是一样的):

def raiseError(e:Throwable):单位=println(e.getMessage)
def firstMethod(v:Int):要么[Throwable,Int]=Right(v*2)
def secondMethod(v:Int):或者[Throwable,Int]=Try(v/0)。toEither
def thirdMethod(v:Int):任意[Throwable,Int]=Right(v*2)
val x=用于{

首先For comprehension只是一系列
flatMap
调用的语法糖。因此,并非只有任何Scala代码都可以进入您的内部进行理解。以下是您试图做的不合法Scala的事情之一:

//This does not compile because normal if-else statements are not valid inside a for comprehension
object Example1 {
  def f(o: Option[Int]): Option[Int] = for {
    x <- o
    if (x < 0) "return some value"
    else { //attempting to continue the for comprehension
      y <- o
    }
  } yield ??? //what would we yield here?
}
但这看起来不像你想要的。它看起来像是你在运行每一步的时候都在试图跟踪异常情况。
Try
Monad正是这样做的,并且可以用于理解。请注意等效的Scala代码,它使用
flatMap
调用而不是a来理解。我建议用all编写函数嵌套的
flatMap
会在尝试转换为更漂亮的语法以便于理解之前调用,如果您陷入困境,请查看一些如何执行此操作的示例

// myFunc1 is equiv to myFunc2 is equiv to myFunc3
// they only differ in syntax
object Example3 {
  import scala.util.Try

  def runStepA[A](in: A): Try[A] = ???
  def runStepB[A](in: A): Try[A] = ???
  def runStepC[A](in: A): Try[A] = ???

  def myFunc1[A](input: A): Try[A] = for {
    nonErrorResultA <- runStepA(input)
    nonErrorResultB <- runStepB(nonErrorResultA)
    nonErrorResultC <- runStepC(nonErrorResultB)
  } yield nonErrorResultC

  def myFunc2[A](input: A): Try[A] =
    runStepA(input).flatMap {
      nonErrorResultA => runStepA(nonErrorResultA).flatMap {
        nonErrorResultB => runStepB(nonErrorResultB).flatMap {
          nonErrorResultC => runStepC(nonErrorResultC)
        }
      }
    }

  def myFunc3[A](input: A): Try[A] =
    runStepA(input).flatMap {
      runStepA(_).flatMap {
        runStepB(_).flatMap {
          runStepC
        }
      }
    }
}
//myFunc1等同于myFunc2等同于myFunc3
//它们只是在语法上有所不同
对象示例3{
导入scala.util.Try
def runStepA[A](在:A中):尝试[A]=???
def runStepB[A](在:A中):尝试[A]=???
def runStepC[A](在:A中):尝试[A]=???
def myFunc1[A](输入:A):请尝试[A]=for{
非错误结果RUNSTEC(非错误结果)
}
}
}
def myFunc3[A](输入:A):尝试[A]=
runStepA(输入).flatMap{
runStepA(u).flatMap{
runStepB(41;).flatMap{
runStepC
}
}
}
}

您是否尝试过直接使用
map
/
flatMap
而不是使用
for
?您可能应该使用
match
而不是
isInstanceOf
。您能给我举个例子说明在这种情况下如何做到这一点吗?我尝试了几种不同的方法,但代码无法编译。您需要给出更多信息在我们提出任何具体建议之前,请先了解类型的详细信息,但请记住,
for(a…
object Example2 {
  def f(o: Option[Int]): Option[Int] = for {
    x <- o
    if x >= 0
  } yield x

  //f and f2 are equivalent functions
  def f2(l: Option[Int]): Option[Int] = l.filter(_ >= 0)
}
// myFunc1 is equiv to myFunc2 is equiv to myFunc3
// they only differ in syntax
object Example3 {
  import scala.util.Try

  def runStepA[A](in: A): Try[A] = ???
  def runStepB[A](in: A): Try[A] = ???
  def runStepC[A](in: A): Try[A] = ???

  def myFunc1[A](input: A): Try[A] = for {
    nonErrorResultA <- runStepA(input)
    nonErrorResultB <- runStepB(nonErrorResultA)
    nonErrorResultC <- runStepC(nonErrorResultB)
  } yield nonErrorResultC

  def myFunc2[A](input: A): Try[A] =
    runStepA(input).flatMap {
      nonErrorResultA => runStepA(nonErrorResultA).flatMap {
        nonErrorResultB => runStepB(nonErrorResultB).flatMap {
          nonErrorResultC => runStepC(nonErrorResultC)
        }
      }
    }

  def myFunc3[A](input: A): Try[A] =
    runStepA(input).flatMap {
      runStepA(_).flatMap {
        runStepB(_).flatMap {
          runStepC
        }
      }
    }
}