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?
CodePudding user response:
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._