Non default constructor type class

For starters, these don’t really look like type classes, but like implicits as depedency injection.
But to answer the question, an implicit def can have implicit parameters. So for you example where you have a service that is made up of other services you could have

trait Service1 { ... }
trait Service2 { ... }

trait AggregatedService {
  def service1: Service1
  def service2: Service2
}
object AggregatedService {
  implicit def mkAS(implicit s1: Service1, s2: Service2) = new AggregatedService {
    val service1 = s1
    val service2 = s2
  }
}

However for your Service[I, O] example it probably doesn’t make sense for I and I => O to be implicitly available. But again these are not really typeclasses. I guess you just want to use implicits as a form of dependency injection here. For that purpose it’s not necessary to implicitly create your Service and it probably wouldn’t make sense anyway (except perhaps for an AggregatedService, or to get a Service1 from an AggregatedService). You just need to have an implicit parameter of Service[I, O] on every class or method that requires access to it. And then you wire up the dependencies at the edge of your application.

object EntryPoint {
  def main(args: Array[String]): Unit = {
    implicit val service1 = new Service1
    implicit val service2 = new Service2
    Application.doMagic()
  }
}

object Application {
   def doMagic()(implicit s1: Service1, s2: Service2) = {
     hocus()
     pocus()
   }

   def hocus()(implicit s1: Service1) = {
     ...
   }
   def pocus()(implicit s2: Service2) = {
     ...
   }
}
2 Likes