I have a http4s project which uses ciris for configuration management.
The project is in github here.
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"
)
When I compile my project I get below error here
[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] ^
The reason is I'm missing implicit parameter which needed by the function here
The error tells me to use use cats.effect.IOApp or build one with cats.effect.IO.contextShift
but couldn't find cats.effect.IOApp
or cats.effect.IO.contextShift
Any Help is appreciated.
There are several popular usages of implicit
and one of them is to to pass some "context" information. The code you look at is a classical example of this usage.
When you do "timeout" there are 2 things you need to decide on:
The important thing about those parameters are that on the one hand they are essential to the job but on the other hand they are only supportive to the main parameter. Another thing is that you probably want to have just one (or very few) global objects that you use everywhere for those things. This is what makes them context and this is why they are passed implicitly.
Now you have a choice of where to get them:
This choice is not a trivial design decision and depends on how are you going to use your API. Typically the correct choice is the first one - make them your context. In that way you allow the caller to setup the context the way it want to (for example, should Timer
and Concurrent
use the same thread pool or different ones?). Sometimes it is OK to create your own independent context. Or to wrap another context you received from outside into something specific to you.
Assuming you want to wrap the outer context at the boundary of your Http4sApi
, you may write a code like this:
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)
Then you can write just
def withTimeout(timeout: Duration)(service: HttpService[IO]): HttpService[IO] = timeout match {
case finite: FiniteDuration => Timeout(finite)(service)
case _ => service
}
and it should compile.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With