我有一些结构上与此相同的代码,但我不确定最好的清理方法是什么?琐碎的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发布于 2019-11-27 16:40:54
正如其他人所提到的,您可以将您的方法提取为子方法。但是,如果您发现这还不够,您可以使用FS2或Monix等库来使您的工作更轻松。它非常适合处理IO +列表的事情。
您可以将流可视化为逐个发出的项的列表。所以,你一次只需要处理一个。
上面的例子可以翻译为(不包括未使用的变量):
Monix:
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()
}https://stackoverflow.com/questions/59050483
复制相似问题