scala-n00b
scala-n00b

Reputation: 23

Make F[_] implementing Monad trait while accepting IO

Let us say we have the code (<: Monad[F] doesn't work as expected):

class External[F[_] <: Monad[F] : Concurrent](implicit proxy: Proxy[F]) { ... }

class Proxy[F[_] <: Monad[F]](implicit storage: Storage, async: Async[F]) {
  def get(key: String): F[Option[Entry]] = {
    async.blocking(storage.get(key))
  }
}

I would like F[_] to be a Monad, so that proxy.get() have those traits and enables for example (inside External class):

proxy.get(key).flatMap(...)

So far so good, but when trying to instantiate with cats.effect.IO it doesn't work for External:

implicit val proxy: Proxy[IO] = new Proxy()
implicit val external: External[IO] = new External()

With error output:

inferred type arguments [[+A]cats.effect.IO[A]] do not conform to value <local External>'s type parameter bounds [F[_] <: cats.Monad[F]]

How can this be fixed or achieved in a different way?

Upvotes: 2

Views: 536

Answers (1)

Dmytro Mitin
Dmytro Mitin

Reputation: 51658

Replace

class External[F[_] <: Monad[F] : Concurrent]

with

class External[F[_]: Monad : Concurrent]

Being a Monad doesn't mean being a subtype of Monad. It means there is an instance of the type class Monad for current type.

On contrary to OOP, in FP implementing some abstract behavior is achieved not with extending/inheritance/subtype polymorphism but with implicits/defining type-class instances/ad hoc polymorphism.

Maybe you need to import necessary syntax:

import cats.syntax.flatMap._

or

import cats.syntax.functor._

or all synaxes at once

import cats.syntax.all._

How to enforce F[_] to be an instance of Monad

https://eed3si9n.com/herding-cats/import-guide.html

Upvotes: 6

Related Questions