0

As a followup to this question I need to process all results collected in processResult. But when I run the code I get <function1> from println(finalBusinessResult)

Edit: It seems to process step1 one and nothing else

Q: How do get it to return the result from processResult

  case class BusinessState()
  trait BusinessResult
  case object KeepGoing extends BusinessResult
  case object StopNow extends BusinessResult
  type IOState[S, A] = StateT[IO, S, A]
  type BusinessIOState[A] = IOState[BusinessState, A]
  trait SomeSteps {
    def step1: BusinessIOState[Unit]
    def step2: BusinessIOState[BusinessState]
    def decisionStep: BusinessIOState[BusinessResult]
    def step3: BusinessIOState[BusinessResult]
    def step4: BusinessIOState[BusinessResult]
    def processResult(businessResult: BusinessResult*): BusinessIOState[BusinessResult]
    def toOpt(a: BusinessIOState[BusinessResult])
    : OptionT[BusinessIOState, BusinessResult] = {
      OptionT.liftF(a).filter(_ == KeepGoing)
    }
    def program: BusinessIOState[Unit] = (for {
      _ <- step1
      _ <- step2
      businessResult <- (for {
        businessResult1 <- toOpt(decisionStep)
        businessResult2 <- toOpt(step3)
        businessResult3 <- toOpt(step4)
      } yield processResult(businessResult1, businessResult2, businessResult3)).getOrElse(())
    } yield businessResult)
  }
  object Impl extends SomeSteps {
    def step1 = Monad[BusinessIOState].unit
    def step2 = Monad[BusinessIOState].pure(BusinessState())
    def decisionStep = StateT.liftF(IO { println("dS"); KeepGoing })
    def step3 = StateT.liftF(IO { println("3"); KeepGoing })
    def step4 = StateT.liftF(IO { println("4"); KeepGoing })
    def processResult(businessResult: BusinessResult*): BusinessIOState[BusinessResult] =
      StateT.liftF(IO { println("5"); KeepGoing })
  }

  def run(args: List[String]) = {

    val finalBusinessResult = for {
      businessResult <- Impl.program.runA(BusinessState())
    } yield businessResult

    println(finalBusinessResult)

    IO.pure(ExitCode.Success)
  }
jakstack
  • 2,143
  • 3
  • 20
  • 37
  • Seems like `finalBusinessResult` returning some sort or function value, can you please check the `type` of `finalBusinessResult`. You may want to invoke the function in order to get value before printing it. – Ra Ka Jun 17 '19 at 10:53
  • `finalBusinessResult` appears to be an `IO[Unit]`, which is to be expected because you explicitly tell `program` to return a `BusinessIOState[Unit]`. If you want to have your `BusinessResult`s available, you're going to have to have a different type there - and a different default in `getOrElse`. Also, since `IO` is lazy async, you're going to have to explicitly run `finalBusinessResult` via e.g. `unsafeRunSync` in order to get any of the steps to actually execute. If you do, you'll see the `println` steps trigger. – Astrid Jun 17 '19 at 13:41

1 Answers1

2

With the help of these responses I managed to get it working correctly.

  object StopIO extends IOApp {

  case class BusinessState()
  trait BusinessResult
  case object KeepGoing extends BusinessResult
  case object StopNow extends BusinessResult
  type IOState[S, A] = StateT[IO, S, A]
  type BusinessIOState[A] = IOState[BusinessState, A]

  trait SomeSteps {
    def step1: BusinessIOState[Unit]
    def step2: BusinessIOState[Unit]
    def decisionStep: BusinessIOState[BusinessResult]
    def step3: BusinessIOState[BusinessResult]
    def step4: BusinessIOState[BusinessResult]
    def processResult(businessResult: BusinessResult*): BusinessIOState[BusinessResult]

    def toOpt(a: BusinessIOState[BusinessResult]): OptionT[BusinessIOState, BusinessResult] = {
      OptionT.liftF(a).filter(_ == KeepGoing)
    }

    def program = (for {
      _ <- step1
      _ <- step2
      businessResult <- (for {
        businessResult1 <- toOpt(decisionStep)
        businessResult2 <- toOpt(step3)
        businessResult3 <- toOpt(step4)
        businessResult4 <- toOpt(processResult(businessResult1, businessResult2, businessResult3))
      } yield businessResult4).getOrElse(KeepGoing)
    } yield businessResult)
  }
  object Impl extends SomeSteps {
    def step1 = Monad[BusinessIOState].unit
    def step2 = Monad[BusinessIOState].pure(KeepGoing)
    def decisionStep = StateT.liftF(IO { println("dS"); KeepGoing })
    def step3 = StateT.liftF(IO { println("3"); KeepGoing })
    def step4 = StateT.liftF(IO { println("4"); KeepGoing })
    def processResult(businessResult: BusinessResult*) = StateT.liftF(IO { println("5"); KeepGoing })
  }

  def run(args: List[String]) = {

    val ioResult = for {
     businessResult <- Impl.program.runA(BusinessState())
    } yield businessResult

    println(ioResult.unsafeRunSync())

    IO.pure(ExitCode.Success)
  }
}
jakstack
  • 2,143
  • 3
  • 20
  • 37