我有一些结构与此相同的代码,但我不确定清理它的最佳方法?那里有一些简单的 IO 和添加,因此该示例无需其他方法即可编译。
我真的不想让它如此嵌套,有没有办法让单个理解同时支持 IO 和 List?我知道这个问题的选项变体有 OptionT,但似乎没有等效的 ListT。
如有任何建议,我们将不胜感激
import cats.Traverse
import cats.effect.IO
import cats.implicits._
def exampleDoingSomeThings: IO[Unit] = for {
ids <- IO.pure(List(1, 2, 3))
_ <- ids.traverse[IO, Unit](id => for {
users <- IO.pure(List(id + 4, id + 5, id + 6))
data <- IO(id + 7)
otherData <- IO(id + 8)
_ <- users.traverse[IO, Unit](ud => for {
innerData <- IO(id + ud)
innerState <- IO(ud + 9)
_ <- if (innerState > 15) for {
_ <- IO(println(s"action1: $id $ud"))
_ <- IO(println(s"action2: $id $ud"))
} yield () else IO.pure()
} yield ())
} yield ())
} yield ()
exampleDoingSomeThings.unsafeRunSync
最佳答案
正如其他人提到的,您可以将方法提取到子方法。但是,如果您发现这还不够,您可以使用类似 FS2 的库。或Monix让您的生活更轻松。它非常适合处理 IO + List 事物。
您可以将流可视化为逐项发出的项目列表。因此,您一次只需处理一个。
上面的例子可以翻译为(不包括未使用的变量):
莫尼克斯:
def monixThings: Observable[Unit] = for {
id <- Observable.fromIterable(List(1, 2, 3))
ud <- Observable.fromIterable(List(id + 4, id + 5, id + 6))
innerState <- Observable.pure(ud + 9)
_ <- Observable.fromTask {
if (innerState > 15) {
for {
_ <- Task.delay(println(s"action1: $id $ud"))
_ <- Task.delay(println(s"action2: $id $ud"))
} yield ()
} else {
Task.unit
}
}
} yield ()
monixThings.completedL.runSyncUnsafe()
https://scalafiddle.io/sf/BDKbGCq/0
FS2:
import cats.effect.IO
import fs2.Stream
object FS2Example extends App {
def fs2Things = for {
id <- Stream.emits(List(1, 2, 3))
ud <- Stream.emits(List(id + 4, id + 5, id + 6))
innerState <- Stream.emit(ud + 9)
_ <- Stream.eval {
if (innerState > 15) {
for {
_ <- IO(println(s"action1: $id $ud"))
_ <- IO(println(s"action2: $id $ud"))
} yield ()
} else {
IO.unit
}
}
} yield ()
fs2Things.compile.drain.unsafeRunSync()
}
关于scala - 如何用 scala cats 效果中的遍历来展平 for-compression ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59050483/