如果 Option 是 None 使用 cats IO,如何停止执行 for-comprehension?

How to stop execution in for-comprehension if Option is None using cats IO?

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

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

但是如何使用 cat 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()

结果我得到 a b c,但我预计只有 a b

是否可以实现?这是正确的做法吗?

你可以用 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() 

查看实际效果 here