我正在Scala和Cats中创建一个执行一些I / O的函数,该函数将被代码的其他部分调用。我也在学习Cats,并且希望我的功能:
F[_]
我假设我的所有函数在F [_]中都是通用的,直到main方法为止,因为我试图遵循these Cat's guidelines
但是我很难通过使用ContextShift
或ExecutionContext
使这些约束起作用。我写了一个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,并且希望我的功能能够:在效果上具有通用性,并使用...
所以我自由地重写了您的代码,希望对您有所帮助: