【问题标题】:How to wrap a method having implicits with another method in Scala?如何用Scala中的另一种方法包装具有隐含的方法?
【发布时间】:2020-07-06 00:07:42
【问题描述】:

我有一个隐式方法:

def f(x: String)(implicit dispatcher: ExecutionContextExecutor, mat: ActorMaterializer) = ???

我想创建一个辅助方法,例如:

def g1(y: String) = f("uri1" + y)
def g2(y: String) = f("uri2" + y)

当然,对于方法g,这不能编译为no implicits found for parameter ex: ExecutionContext

我不想在g 中重复implicits 声明。
那么,这种情况的惯用解决方案是什么?

【问题讨论】:

  • 惯用的解决方案是重复隐式声明。如果所有方法都是同一个类的一部分,你可以将隐式移到类的构造函数中。

标签: scala implicit


【解决方案1】:

惯用的解决方案是重复隐式参数。

如果您多次重复同一组隐式参数,那么惯用的解决方案是引入您的类型类(或只是单个隐式)而不是那组隐式并使用此类型类。

不惯用的解决方案是引入将为方法生成隐式参数部分的宏注释。

有时您可以将隐式转移到更高的某个级别

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
}

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
}

能否请您也举一个 typeclass 的例子?

假设你有多个类型类

trait TC1[A] {
  def foo = ???
}
trait TC2[A] {
  def bar = ???
}

你必须在方法中重复它们

def f[A](implicit tc1: TC1[A], tc2: TC2[A]) = ???

1.然后你可以介绍你的类型类

trait TC[A] {
  def foo
  def bar
}

通过TC1TC2、...表达它

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
  }
}

并使用它

def f[A](implicit tc: TC[A]) = ???

2.替代方法是

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._
  ???
}

在您使用ExecutionContextExecutorActorMaterializer 的示例中(例如遵循第二种方法),您可以引入

trait MyImplicit {
  implicit def dispatcher: ExecutionContextExecutor
  implicit def mat: ActorMaterializer
}

替换

def f(x: String)(implicit dispatcher: ExecutionContextExecutor, mat: ActorMaterializer) = ???

def f(x: String)(implicit mi: MyImplicit) = {
  import mi._
  ???
}

【讨论】:

  • 能否也举一个typeclass的例子?我还是新手。
  • @user6502167 typeclass 解决方案不适用于您的情况。因为它旨在将多个隐式组合为一个,但您只有一个。但这是一个很好的学习模式
  • 我用多个隐式更新了这个问题。 @LuisMiguelMejíaSuárez
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-28
相关资源
最近更新 更多