user451151 user451151 - 1 month ago 11
Scala Question

Bring implicit parameter into scope from within case class body

How would I do something like the following (this is obviously a silly example, but it serves to illustrate my question):

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


This causes the error:

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


This is obviously a scope issue; the
map2bool
implicit isn't in scope and, as such,
getString
fails.

Is there a way I can somehow bring this into scope? The reason I put it in the body of
MapBoolGetString
is because I want it to rely on the
name
argument to the constructor within
map2bool
.

Answer Source

You can import members of instances in Scala to bring them into scope, and they keep implicitness:

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

As a side note, there's no reason to define both toString and getString; if you pass something other than U to toString, Scala will look for implicit conversions in scope automatically.