我如何抽象效果并在Scala Cats中使用ContextShift?

问题描述 投票:1回答:1

我正在Scala和Cats中创建一个执行一些I / O的函数,该函数将被代码的其他部分调用。我也在学习Cats,并且希望我的功能:

  • 发挥作用并使用F[_]
  • 在专用线程池上运行
  • 我想引入异步边界

我假设我的所有函数在F [_]中都是通用的,直到main方法为止,因为我试图遵循these Cat's guidelines

但是我很难通过使用ContextShiftExecutionContext使这些约束起作用。我写了一个full example here,这是从示例中摘录的内容:

object ComplexOperation {
  // Thread pool for ComplexOperation internal use only
  val cs = IO.contextShift(
    ExecutionContext.fromExecutor(Executors.newSingleThreadExecutor())
  )

  // Complex operation that takes resources and time
  def run[F[_]: Sync](input: String): F[String] =
    for {
      r1 <- Sync[F].delay(cs.shift) *> op1(input)
      r2 <- Sync[F].delay(cs.shift) *> op2(r1)
      r3 <- Sync[F].delay(cs.shift) *> op3(r2)
    } yield r3

  def op1[F[_]: Sync](input: String): F[Int]     = Sync[F].delay(input.length)
  def op2[F[_]: Sync](input: Int): F[Boolean]    = Sync[F].delay(input % 2 == 0)
  def op3[F[_]: Sync](input: Boolean): F[String] = Sync[F].delay(s"Complex result: $input")
}

这显然不会抽象出效果,因为ComplexOperation.run需要ContextShift[IO]才能引入异步边界。什么是正确(或最佳)方法?

ContextShift[IO]中创建ComplexOperation.run使该功能取决于我不需要的IO。在调用者上移动ContextShift[IO]的创建将简单地转移问题:调用者在F[_]中也是通用的,那么它如何获得ContextShift[IO]传递给ComplexOperation.run而不显式依赖IO?] >

请记住,我不想使用在最高级别定义的一个全局ContextShift[IO],但我希望每个组件自行决定。

我的ComplexOperation.run应该创建ContextShift[IO]还是呼叫者的责任?

我至少正确地做到了吗?还是我违反标准做法?

我正在Scala和Cats中创建一个执行一些I / O的函数,该函数将被代码的其他部分调用。我也在学习Cats,并且希望我的功能能够:在效果上具有通用性,并使用...

scala generics concurrency scala-cats
1个回答
2
投票

所以我自由地重写了您的代码,希望对您有所帮助:

© www.soinside.com 2019 - 2024. All rights reserved.