将隐式参数放入case类体内的范围

时间:2017-07-02 18:17:11

标签: scala

我如何做以下事情(这显然是一个愚蠢的例子,但它可以说明我的问题):

trait GetString[T, U] {
  def toString(u: U): String = u.toString
  final def getString(t: T)(implicit f: (T) => U) = toString(f(t))
}

case class MapBoolGetString(name: String) extends GetString[Map[String, String], Boolean] {
  /* This does not work */
  implicit val map2bool = (m: Map[String, String]) => m.contains(name)
}

class Main {
  val test = MapBoolGetString("key")
  test.getString(Map("key" -> "value"))
}

这会导致错误:

No implicit view available from Map[String,String] => Boolean.

这显然是范围问题; map2bool隐含不在范围内,因此getString失败。

有没有办法可以把它带入范围?我把它放在MapBoolGetString主体中的原因是因为我希望它依赖于name中构造函数的map2bool参数。

1 个答案:

答案 0 :(得分:1)

您可以在Scala中import个实例成员将它们纳入范围,并保持隐含性:

val test = MapBoolGetString("key")
import test.map2bool
test.getString(Map("key" -> "value"))

作为旁注,没有理由同时定义toStringgetString;如果您将U以外的内容传递给toString,Scala会自动在范围内查找隐式转换。

  

有什么办法可以让你想到实现这个而不需要明确的导入声明吗?我很乐意,如果它是MapBoolGetString实例化的一部分。

不是真的,但如果你只需要一个隐含的,你可以这样做:

case class MapBoolGetString(name: String) extends GetString[Map[String, String], Boolean] with Map[String, String] => Boolean {
  def apply(m: Map[String, String]) = m.contains(name)
}

// in Main
implicit val test = MapBoolGetString("key")
test.getString(Map("key" -> "value"))