0

I have a working code:

final case class Services[F[_]](c: Client[F], fooUrl: String)
                               (implicit cf: ConcurrentEffect[F]) {

  private val dsl = Http4sDsl[F]

  import dsl._

  def routes: HttpRoutes[F] = HttpRoutes.of[F] {
    case GET -> Root / "call" =>
      c.get(fooUrl) { res =>
        Applicative[F].pure {
          Response[F]().withEntity {
            res
              .body
              .through(text.utf8Decode)
              .map(msg => "Forwarded through Boo" |+| msg)
          }
        }
      }
  }

When I would delete the implicit import implicit cf: ConcurrentEffect[F], then compiler will complain:

[error] /home/developer/scala/boo-service/src/main/scala/com/sweetsoft/Services.scala:29:20: could not find implicit value for parameter instance: cats.Applicative[F]
[error]         Applicative[F].pure {
[error]                    ^
[error] /home/developer/scala/boo-service/src/main/scala/com/sweetsoft/Services.scala:26:48: could not find implicit value for evidence parameter of type cats.Defer[F]
[error]   def routes: HttpRoutes[F] = HttpRoutes.of[F] {
[error]                                                ^
[error] two errors found

How do I know, the type class implicit cf: ConcurrentEffect[F] is missing?

softshipper
  • 32,463
  • 51
  • 192
  • 400
  • 1
    Well the error message is pretty clear, on some point you need an **Applicative[F]** on other point you need a **Defer[F]** given a **Defer** is an **Applicative** you just need that. PS: **ConcurrentEffect** is a **Defer** plus other things, so that is why it works. But you may chose something less strict. – Luis Miguel Mejía Suárez Dec 26 '19 at 13:08
  • Where did you find, that `ConcurrentEffect is a Defer `? – softshipper Dec 26 '19 at 13:15
  • 1
    I've this https://typelevel.org/cats-effect/api/cats/effect/Sync.html. Is it correct right? – softshipper Dec 26 '19 at 13:16
  • 2
    This could be helpful: https://github.com/tpolecat/cats-infographic – Haemin Yoo Dec 26 '19 at 13:22
  • 1
    Yeah, what @HaeminYoo shared is great to know what constraints each **typeclass** satisfy. Also, I made a mistake. **Defer** is not an **Applicative**, I confused it with **Sync** which is a **Defer** with a **Bracket** _(which it is an **Applicative**)_. Thus, the least powerful abstraction that you need there is a **Sync** - Now, a **ConcurrentEffect** is an **Effect** + a **Concurrent**, an **Effect** is an **Async** and an **Async** is a **Sync**. You can check all that on the infographic, or following the scaladoc or in the official [docs](https://typelevel.org/cats-effect/typeclasses) – Luis Miguel Mejía Suárez Dec 26 '19 at 13:31

1 Answers1

3

I think the answer you can get if you will look to sources of cats-effect library:

Lets go to ConcurrentEffect definition:

trait ConcurrentEffect[F[_]] extends Concurrent[F] with Effect[F] {...

Hmm, now let's look at Concurrent:

trait Concurrent[F[_]] extends Async[F] {...

Async:

trait Async[F[_]] extends Sync[F] with LiftIO[F] {...

Next:

trait Sync[F[_]] extends Bracket[F, Throwable] with Defer[F] {

Now we can conclude that ConcurrentEffect extends Defer

The same try to do with Applicative yourself ;)

To handle such an errors fast - I think you have to understand extensions hierarchy - so you can fastly figure out which typeclass you need

oybek
  • 630
  • 4
  • 14