Idiomatic solution is to repeat implicit parameters.
If you repeat the same set of implicit parameters many times then idiomatic solution is to introduce your type class (or just single implicit) instead of that set of implicits and use this type class.
Not idiomatic solution is to introduce macro annotation that will generate implicit parameter section for methods.
Sometimes you can transfer implicits to some level above
class MyClass(implicit val ec: ExecutionContext) extends ExecutionContextAware {
def f(x: String) = ???
def g(y: String) = f("xxx" + y)
}
trait ExecutionContextAware {
implicit def ec: ExecutionContext
}
or
trait MyTrait extends ExecutionContextAware {
def f(x: String) = ???
def g(y: String) = f("xxx" + y)
}
object Impl extends ExecutionContextAware {
implicit def ec: ExecutionContext = ExecutionContext.Implicits.global
}
trait ExecutionContextAware {
implicit def ec: ExecutionContext
}
Could you please also give an example with typeclass?
Suppose you have multiple type classes
trait TC1[A] {
def foo = ???
}
trait TC2[A] {
def bar = ???
}
and you have to repeat them in methods
def f[A](implicit tc1: TC1[A], tc2: TC2[A]) = ???
1. Then you can introduce your type class
trait TC[A] {
def foo
def bar
}
express it via TC1
, TC2
, ...
object TC {
implicit def mkTC[A](implicit tc1: TC1[A], tc2: TC2[A]): TC[A] = new TC[A] {
def foo = tc1.foo
def bar = tc2.bar
}
}
and use it
def f[A](implicit tc: TC[A]) = ???
2. Alternative approach is
trait TC[A] {
implicit def tc1: TC1[A]
implicit def tc2: TC2[A]
}
object TC {
implicit def mkTC[A](implicit _tc1: TC1[A], _tc2: TC2[A]): TC[A] = new TC[A] {
implicit def tc1: TC1[A] = _tc1
implicit def tc2: TC2[A] = _tc2
}
}
def f[A](implicit tc: TC[A]) = {
import tc._
???
}
In your example with ExecutionContextExecutor
, ActorMaterializer
(for example following the 2nd approach) you can introduce
trait MyImplicit {
implicit def dispatcher: ExecutionContextExecutor
implicit def mat: ActorMaterializer
}
and replace
def f(x: String)(implicit dispatcher: ExecutionContextExecutor, mat: ActorMaterializer) = ???
with
def f(x: String)(implicit mi: MyImplicit) = {
import mi._
???
}