找不到ContextShift的隐含值。

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

我试图用http4s创建基于Http4sServlet的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?

scala scala-cats http4s cats-effect
1个回答
2
投票

Context shift只是猫的包装器,它是在 ExecutionContext. 你可以明确地创建一个 陈述 在文档中。

implicit val cs: ContextShift[IO] = IO.contextShift(ExecutionContext.global)

你通常会在你的应用的入口处创建一个上下文转移(可能在主方法中)。

如果您的应用程序使用 IOApp 它已经在范围内隐含了contextShift。它将使用执行上下文,它的线程数等于你计算机的可用处理器数。

如果你想在你的应用程序中 "深入 "使用创建的contextShift,你可以把它作为一个隐式参数传递。

def doSomething(implicit cs: ContextShift[IO]): IO[Unit] = ???

所以为了让你的代码正常工作, 你需要确保方法或类调用Constructor of 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())

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