找不到 ContextShift 的隐式值
Cannot find an implicit value for ContextShift
我正在尝试使用基于 Http4sServlet 的 http4s 创建 webapp。
以下代码无法编译:
import cats.effect._
import org.http4s.servlet.BlockingServletIo
import org.http4s.servlet.Http4sServlet
import scala.concurrent.ExecutionContext.global
import org.http4s.implicits._
class UserSvcServlet
extends Http4sServlet[IO](service = UserSvcServer.start
, servletIo = BlockingServletIo(4096, Blocker.liftExecutionContext(global)))(IOApp)
错误信息:
[error] /home/developer/scala/user-svc/src/main/scala/io/databaker/UserSvcServlet.scala:12:54: Cannot find implicit value for ConcurrentEffect[[+A]cats.effect.IO[A]].
[error] Building this implicit value might depend on having an implicit
[error] s.c.ExecutionContext in scope, a Scheduler, a ContextShift[[+A]cats.effect.IO[A]]
[error] or some equivalent type.
[error] extends Http4sServlet[IO]( service = UserSvcServer.stream
[error] ^
[error] /home/developer/scala/user-svc/src/main/scala/io/databaker/UserSvcServlet.scala:13:36: Cannot find an implicit value for ContextShift[[+A]cats.effect.IO[A]]:
[error] * import ContextShift[[+A]cats.effect.IO[A]] from your effects library
[error] * if using IO, use cats.effect.IOApp or build one with cats.effect.IO.contextShift
[error] , servletIo = BlockingServletIo(4096, Blocker.liftExecutionContext(global)))
[error] ^
[error] two errors found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 1 s, completed May 29, 2020, 8:45:00 PM
UserSvcServer
实现如下:
import org.http4s.HttpApp
import cats.effect.{ConcurrentEffect, ContextShift, Timer}
import org.http4s.implicits._
import org.http4s.server.middleware.Logger
object UserSvcServer {
def start[F[_] : ConcurrentEffect](implicit T: Timer[F], C: ContextShift[F]): HttpApp[F] = {
val helloWorldAlg = HelloWorld.impl[F]
val httpApp = UserSvcRoutes.helloWorldRoutes[F](helloWorldAlg).orNotFound
Logger.httpApp(true, true)(httpApp)
}
}
如何隐式导入 ContextShift?
上下文转换只是猫对 ExecutionContext
的包装。您可以在文档中明确创建一个 stated:
implicit val cs: ContextShift[IO] = IO.contextShift(ExecutionContext.global)
您通常会在应用程序的入口点创建一个上下文转换(可能在 main 方法中)。
如果您的应用使用来自 cats-effect 的 IOApp
,那么它已经隐含了范围内的 contextShift。它将使用执行上下文,其线程数等于您计算机的可用处理器。
如果您想在应用程序中使用创建的 contextShift "deeper",您可以将其作为隐式参数传递:
def doSomething(implicit cs: ContextShift[IO]): IO[Unit] = ???
因此,为了使您的代码正常工作,您需要确保方法或 class 调用 UserSvcServlet
的构造函数具有隐含的 contextShift:
(implicit cs: ContextShift[IO])
.
您也可以将其放在单独的对象中:
object AppContextShift {
implicit val cs: ContextShift[IO] = IO.contextShift(ExecutionContext.global)
implicit val t: Timer[IO] = IO.timer(ExecutionContext.global) //you will probably also need timer eventually
}
然后需要contextShift的时候导入即可:
import AppContextShift._
顺便说一下,为 Blocker 使用全局执行上下文不是个好主意。
Blocked 用于阻塞操作,将其与 ExecutionContext.global
一起使用可能会导致您的应用程序中的线程不足。
最常见的方法是使用从缓存线程池创建的阻塞程序:
Blocker.liftExecutorService(Executors.newCachedThreadPool())
我正在尝试使用基于 Http4sServlet 的 http4s 创建 webapp。 以下代码无法编译:
import cats.effect._
import org.http4s.servlet.BlockingServletIo
import org.http4s.servlet.Http4sServlet
import scala.concurrent.ExecutionContext.global
import org.http4s.implicits._
class UserSvcServlet
extends Http4sServlet[IO](service = UserSvcServer.start
, servletIo = BlockingServletIo(4096, Blocker.liftExecutionContext(global)))(IOApp)
错误信息:
[error] /home/developer/scala/user-svc/src/main/scala/io/databaker/UserSvcServlet.scala:12:54: Cannot find implicit value for ConcurrentEffect[[+A]cats.effect.IO[A]].
[error] Building this implicit value might depend on having an implicit
[error] s.c.ExecutionContext in scope, a Scheduler, a ContextShift[[+A]cats.effect.IO[A]]
[error] or some equivalent type.
[error] extends Http4sServlet[IO]( service = UserSvcServer.stream
[error] ^
[error] /home/developer/scala/user-svc/src/main/scala/io/databaker/UserSvcServlet.scala:13:36: Cannot find an implicit value for ContextShift[[+A]cats.effect.IO[A]]:
[error] * import ContextShift[[+A]cats.effect.IO[A]] from your effects library
[error] * if using IO, use cats.effect.IOApp or build one with cats.effect.IO.contextShift
[error] , servletIo = BlockingServletIo(4096, Blocker.liftExecutionContext(global)))
[error] ^
[error] two errors found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 1 s, completed May 29, 2020, 8:45:00 PM
UserSvcServer
实现如下:
import org.http4s.HttpApp
import cats.effect.{ConcurrentEffect, ContextShift, Timer}
import org.http4s.implicits._
import org.http4s.server.middleware.Logger
object UserSvcServer {
def start[F[_] : ConcurrentEffect](implicit T: Timer[F], C: ContextShift[F]): HttpApp[F] = {
val helloWorldAlg = HelloWorld.impl[F]
val httpApp = UserSvcRoutes.helloWorldRoutes[F](helloWorldAlg).orNotFound
Logger.httpApp(true, true)(httpApp)
}
}
如何隐式导入 ContextShift?
上下文转换只是猫对 ExecutionContext
的包装。您可以在文档中明确创建一个 stated:
implicit val cs: ContextShift[IO] = IO.contextShift(ExecutionContext.global)
您通常会在应用程序的入口点创建一个上下文转换(可能在 main 方法中)。
如果您的应用使用来自 cats-effect 的 IOApp
,那么它已经隐含了范围内的 contextShift。它将使用执行上下文,其线程数等于您计算机的可用处理器。
如果您想在应用程序中使用创建的 contextShift "deeper",您可以将其作为隐式参数传递:
def doSomething(implicit cs: ContextShift[IO]): IO[Unit] = ???
因此,为了使您的代码正常工作,您需要确保方法或 class 调用 UserSvcServlet
的构造函数具有隐含的 contextShift:
(implicit cs: ContextShift[IO])
.
您也可以将其放在单独的对象中:
object AppContextShift {
implicit val cs: ContextShift[IO] = IO.contextShift(ExecutionContext.global)
implicit val t: Timer[IO] = IO.timer(ExecutionContext.global) //you will probably also need timer eventually
}
然后需要contextShift的时候导入即可:
import AppContextShift._
顺便说一下,为 Blocker 使用全局执行上下文不是个好主意。
Blocked 用于阻塞操作,将其与 ExecutionContext.global
一起使用可能会导致您的应用程序中的线程不足。
最常见的方法是使用从缓存线程池创建的阻塞程序:
Blocker.liftExecutorService(Executors.newCachedThreadPool())