Scala 如何生成具有cats效果的可遍历对象';s IO给定了一个将多次调用的异步
我真正想做的是监视多个文件,当其中任何一个文件被修改时,我想更新一些状态,并使用这种状态产生副作用。我想我想要的是对一个可遍历的进行Scala 如何生成具有cats效果的可遍历对象';s IO给定了一个将多次调用的异步,scala,scala-cats,cats-effect,Scala,Scala Cats,Cats Effect,我真正想做的是监视多个文件,当其中任何一个文件被修改时,我想更新一些状态,并使用这种状态产生副作用。我想我想要的是对一个可遍历的进行扫描,生成一个可遍历的[IO[\u]]。但我看不到那条路 作为一个最小的尝试,我写了这篇文章 package example import better.files.{File, FileMonitor} import cats.implicits._ import com.monovore.decline._ import cats.effect.IO impo
扫描
,生成一个可遍历的[IO[\u]]。但我看不到那条路
作为一个最小的尝试,我写了这篇文章
package example
import better.files.{File, FileMonitor}
import cats.implicits._
import com.monovore.decline._
import cats.effect.IO
import java.nio.file.{Files, Path}
import scala.concurrent.ExecutionContext.Implicits.global
object Hello extends CommandApp(
name = "cats-effects-playground",
header = "welcome",
main = {
val filesOpts = Opts.options[Path]("input", help = "input files")
filesOpts.map { files =>
IO.async[File] { cb =>
val watchers = files.map { path =>
new FileMonitor(path, recursive = false) {
override def onModify(file: File, count: Int) = cb(Right(file))
}
}
watchers.toList.foreach(_.start)
}
.flatMap(f => IO { println(f) })
.unsafeRunSync
}
}
)
但这有两大缺陷。它为我正在观看的每个文件创建一个线程,这有点重。但更重要的是,只要修改一个文件,程序就会立即完成,即使如果程序保持运行,onModify
会被调用更多次
我不喜欢使用更好的文件,这似乎是一条阻力最小的道路。但是我确实需要使用Cats IO。这个解决方案不能解决创建一堆线程的问题,也不能严格地生成可遍历的线程,但它解决了底层用例。我非常愿意接受批评,并提供更好的解决方案
package example
import better.files.{File, FileMonitor}
import cats.implicits._
import com.monovore.decline._
import cats.effect.IO
import java.nio.file.{Files, Path}
import java.util.concurrent.LinkedBlockingQueue
import scala.concurrent.ExecutionContext.Implicits.global
object Hello extends CommandApp(
name = "cats-effects-playground",
header = "welcome",
main = {
val filesOpts = Opts.options[Path]("input", help = "input files")
filesOpts.map { files =>
val bq: LinkedBlockingQueue[IO[File]] = new LinkedBlockingQueue()
val watchers = files.map { path =>
new FileMonitor(path, recursive = false) {
override def onModify(file: File, count: Int) = bq.put(IO(file))
}
}
def ioLoop(): IO[Unit] = bq.take()
.flatMap(f => IO(println(f)))
.flatMap(_ => ioLoop())
watchers.toList.foreach(_.start)
ioLoop.unsafeRunSync
}
}
)