Не удается найти неявное значение для ContextShift [cats.effect.IO] в версии 19.0.0 http4s - PullRequest
0 голосов
/ 07 января 2019

У меня есть проект http4s, который использует ciris для управления конфигурацией.

Проект находится в github здесь .

libraryDependencies ++= Seq(
  "is.cir" %% "ciris-cats",
  "is.cir" %% "ciris-cats-effect",
  "is.cir" %% "ciris-core",
  "is.cir" %% "ciris-enumeratum",
  "is.cir" %% "ciris-refined"
).map(_ % "0.12.1")

libraryDependencies ++= Seq(
  "org.http4s" %% "http4s-dsl",
  "org.http4s" %% "http4s-blaze-server"
).map(_ % "0.18.18")

libraryDependencies ++= Seq(
  "com.ovoenergy" %% "ciris-kubernetes" % "0.5",
  "org.typelevel" %% "kittens" % "1.2.0",
  "eu.timepit" %% "refined-cats" % "0.9.3"
)

Когда я компилирую свой проект, я получаю ошибку ниже здесь

    [info] Compiling 12 Scala sources to /Users/rajkumar.natarajan/Documents/Coding/OS/ciris-example/target/scala-2.12/classes ...
    [error] /Users/rajkumar.natarajan/Documents/Coding/OS/ciris-example/src/main/scala/is/cir/example/application/Http4sApi.scala:24:68: Cannot find an implicit value for ContextShift[cats.effect.IO]:
    [error] * import ContextShift[cats.effect.IO] from your effects library
    [error] * if using IO, use cats.effect.IOApp or build one with cats.effect.IO.contextShift
    [error]   implicit val ioConcurrentEffect: Concurrent[IO] = cats.effect.IO.ioConcurrentEffect
    [error]                                                                    ^
    [error] /Users/rajkumar.natarajan/Documents/Coding/OS/ciris-example/src/main/scala/is/cir/example/application/Http4sApi.scala:43:69: type mismatch;
    [error]  found   : (ec: scala.concurrent.ExecutionContext, sc: java.util.concurrent.ScheduledExecutorService)cats.effect.Timer[cats.effect.IO] <and> (ec: scala.concurrent.ExecutionContext)cats.effect.Timer[cats.effect.IO]
    [error]  required: cats.effect.Timer[cats.effect.IO]
    [error]         Timeout(finite)(service)(ioConcurrentEffect, cats.effect.IO.timer)
    [error]                                                                     ^

Причина в том, что мне не хватает неявного параметра, который необходим функции здесь Ошибка говорит мне использовать use cats.effect.IOApp or build one with cats.effect.IO.contextShift, но не может найти cats.effect.IOApp или cats.effect.IO.contextShift

Любая помощь приветствуется.

1 Ответ

0 голосов
/ 07 января 2019

Я подозреваю, что вы не понимаете, как implicit используется в Scala. Существует несколько популярных способов использования , и одним из них является использование имплицитов для передачи некоторой "контекстной" информации. Код, на который вы смотрите, является классическим примером такого использования.

Когда вы делаете «тайм-аут», вам нужно выбрать две вещи:

  • где (в каком потоке) основное задание будет выполняться на
  • где (в каком потоке) будет запущен таймер, поскольку в мире JVM (в отличие от JavaScript, например) нет стандартного таймера.

Важным в этих параметрах является то, что, с одной стороны, они важны для работы, но, с другой стороны, они поддерживают только основной параметр. Другое дело, что вы, вероятно, хотите иметь только один (или очень мало) глобальных объектов, которые вы используете повсюду для этих целей. Это то, что делает их контекстом, и поэтому они передаются неявно.

Теперь у вас есть выбор, где их взять:

  • также сделайте их своим контекстом, то есть заставьте звонящего передать их вам (также неявно
  • создайте свои собственные экземпляры

Этот выбор не является тривиальным дизайнерским решением и зависит от того, как вы собираетесь использовать свой API. Как правило, правильный выбор - первый - сделайте их своим контекстом. Таким образом, вы позволяете вызывающей стороне устанавливать контекст так, как он хочет (например, должны ли Timer и Concurrent использовать один и тот же пул потоков или разные?). Иногда это нормально, чтобы создать свой собственный независимый контекст. Или обернуть другой контекст, который вы получили извне, во что-то конкретное для вас.

Предполагая, что вы хотите обернуть внешний контекст на границе вашего Http4sApi, вы можете написать код, подобный следующему:

final case class Http4sApi()(implicit executionContext: ExecutionContext) extends HttpApiAlg[IO] {
  // create IO-specific context from the executionContext
  private implicit val cs = IO.contextShift(executionContext)
  private implicit val timer = IO.timer(executionContext)

Тогда вы можете написать просто

def withTimeout(timeout: Duration)(service: HttpService[IO]): HttpService[IO] = timeout match {
    case finite: FiniteDuration => Timeout(finite)(service)
    case _                      => service
}

и он должен скомпилироваться.

...