如果选项为无使用猫IO,如何在for-comprehension中停止执行?

Nic*_*yan 7 monads functional-programming scala scala-cats

如果我只是使用选项进行理解,一切都按预期进行:

val a = Some(1)
val b = None
val c = Some(3)

val r = for {
  aa <- a
  bb <- b
  cc <- c
} yield aa + bb + cc

println(r) // None, because b is None
Run Code Online (Sandbox Code Playgroud)

但如何使用猫IO实现相同的行为?

import cats.effect.IO
// in reality this will be a methods with side effect
val a = Some(1)
val b = None
val c = Some(3)

val r = for {
  _ <- IO{println("a"); a}
  _ <- IO{println("b"); b} // want to stop execution here
  _ <- IO{println("c"); c}
} yield ()

r.unsafeRunSync()
Run Code Online (Sandbox Code Playgroud)

结果我得到了a b c,但我只期待a b.

有可能实现吗?这是一种正确的方法吗?

eri*_*rip 7

你可以用monad变换器做到这一点; 具体来说,你想在OptionT[IO, T]这里使用:

import cats.effect._
import cats.data.OptionT
import cats.implicits._
import cats.effect.IO

val a = Some(1)
val b = None
val c = Some(3)

val r = for {
  _ <- OptionT[IO, Int](IO {println("a"); a})
  _ <- OptionT[IO, Int](IO {println("b"); b})
  _ <- OptionT[IO, Int](IO {println("c"); c})
} yield ()

r.value.unsafeRunSync() 
Run Code Online (Sandbox Code Playgroud)

这里看到它.