I have a Service that looks like this:
The Tagless final trait:
trait ProvisioningAPIService[M[_]] {
def provisionAPI(request: Request): M[Response]
}
And somewhere in my implementation, I have the following:
class ProvisioningService extends ProvisioningAPIService[Task] {
def provisionAPI(request: Request): Task[Response] = Task {
Response("response from server")
}
}
This is fine, but I would like to still delay that and pass in the effect only when I instantiate a new version of my ProvisioningService. For example., I would like to have something like this:
class ProvisioningService[M[_]: Monad](implicit monad: Monad[M[_]) extends ProvisioningAPIService[M] {
def provisionAPI(request: Request): M[Response] = /* some wrapper that would be resolved at runtime */ {
Response("response from server")
}
}
And during runtime, I do the following:
val privisioingServiceAsTask = new ProvisioningService[Task]
So basically I do not provide a concrete implemenattion during compile time, but I create an instance of my ProvisioningService passing in an effect at Runtime. How can I do this?
Moving the comment to an answer,
Saying
class MyClass[A : Monad]is the exact same thing is as sayingclass MyClass[A](implicit m: Monad[A])so you don't need both. In this case you will actually want to be able to call it by name so you should prefer the latter.You can read about context bounds for Scala 3 here and Scala 2 here
Now let's look at what Type Classes. Type classes essentially enable overloading per type basis in a nice way.
So when you say you have a
Monad[A]defined in the scope, it means thatAwill have the 3 operations theMonadtrait contains defined. The details of the implementation are abstracted away so we don't have to worry about them. If you look at the page for Monad and by extension Applicative you will see that any instance of a Monad requires you to have an implementation ofPurewhich wraps a value inside the type constructor. What thispuredoes will be left to the implementation of the instance for a given effect. It can beFuture.successfulfor example.So you can have something along the lines of
Hope this answers your question