如何显式传递隐式参数?

问题描述 投票:0回答:1

如果我们定义以下函数:

def methodWithImplicit(explicit: String)(implicit imp: String) = {
  println(explicit + imp)
}

我们可以这样称呼它:

methodWithImplicit("abc")("efg") //abc - explicit, efg - imp

它工作正常。现在考虑以下TypeClass:

trait MyTypeClass[T] {
  def accept(t: T): T
}

将在提取器对象中使用:

object TestExtractor {
  def unapply(str: String)(implicit myTypeClass: MyTypeClass[String]): Option[String] =
    if (!str.isEmpty)
      Some(myTypeClass.accept(str))
    else
      None
}

所以,如果我们按如下方式使用它:

implicit val myTypeClass:MyTypeClass[String] = new MyTypeClass[String] {
  override def accept(t: String): Unit = t
}

"123" match {
  case TestExtractor(str) => println(str)
}

它工作正常。但是在使用模式匹配时如何显式传递参数?我试过了

"123" match {
  case TestExtractor(str)(myTypeClass) => println(str) //compile error
}

"123" match {
  case TestExtractor(myTypeClass)(str) => println(str) //compile error
}

但它没有编译。

scala pattern-matching implicit
1个回答
2
投票

由于左侧似乎基本上只接受由稳定标识符,常量文字和变量名称的小写字母构建的树,因此我没有看到任何方法来接近所需的语法:

val `TestExtractor(myTypeClass)` = TestExtractor(myTypeClass)

"hello" match {
  case `TestExtractor(myTypeClass)`(str) => println(str)
}

这当然要求您在匹配大小写之前定义奇怪命名的值TestExtractor(myTypeClass)(在反引号中),因此您可以将其用作单个符号。

完整代码:

trait MyTypeClass[T] {
  def accept(t: T): T
}

object TestExtractor { outer =>
  def unapply(str: String)(implicit myTypeClass: MyTypeClass[String]): Option[String] =
    if (!str.isEmpty)
      Some(myTypeClass.accept(str))
    else
      None

  class ExplicitTestExtractor(tc: MyTypeClass[String]) {
    def unapply(t: String) = outer.unapply(t)(tc)
  }

  def apply(tc: MyTypeClass[String]): ExplicitTestExtractor = 
    new ExplicitTestExtractor(tc)

}

implicit val myTypeClass:MyTypeClass[String] = new MyTypeClass[String] {
  override def accept(t: String): String = t.toUpperCase
}

val `TestExtractor(myTypeClass)` = TestExtractor(myTypeClass)

"hello" match {
  case `TestExtractor(myTypeClass)`(str) => println(str)
}
© www.soinside.com 2019 - 2024. All rights reserved.