-
-
Save propensive/8894fd2a58ac93bfa2c3 to your computer and use it in GitHub Desktop.
// Define the following traits and companion object | |
// It's in Rapture Core (https://github.com/propensive/rapture-core) if you don't want to | |
trait LowPriorityDefaultsTo { implicit def fallback[T, S]: DefaultsTo[T, S] = null } | |
object DefaultsTo extends LowPriorityDefaultsTo { implicit def defaultDefaultsTo[T]: DefaultsTo[T, T] = null } | |
trait DefaultsTo[T, S] | |
// Then, assuming we want to specify a default for a type class like `Namer`, | |
case class Namer[T](name: String) | |
// where we have a couple of alternatives, | |
implicit val stringNamer = Namer[String]("string") | |
implicit val intNamer = Namer[Int]("int") | |
// we define the default one for a particular method like this: | |
def myMethod[T](implicit default: T DefaultsTo String, namer: Namer[T]) = namer.name | |
// Let's try it out in the REPL: | |
scala> myMethod | |
res0: String = string | |
scala> myMethod[Int] | |
res1: String = int |
Cool! :)
It's even more expectacular if you change it to case class Namer[T](t:T)
, then you get type safety on the default value!
Jon, i wonder why did you place fallback
to LowPriorityDefaultsTo
, if i understand SLS correctly there's no ambiguity between these two implicits, since defaultDefaultsTo
more specific then fallback
, so if we omit the type parameter, the compiler would pick it instead of fallback
, hence no ambiguity. So why placing it on a different layer?
To be sure this compiles on 2.11.7
trait DefaultsTo[Type, Default]
object DefaultsTo {
implicit def fallback[T, D]: DefaultsTo[T, D] = null
implicit def defaultDefaultsTo[T]: DefaultsTo[T, T] = null
}
trait Document
final class Table[DocType](val name: String)(implicit default: DocType DefaultsTo Document)
object Test {
val table = new Table("settings")
val table2 = new Table[String]("settings2")
}
@4lex1v If that works, great! I tend to ignore the type-specificity rules and go straight with stacked traits, but that's a useful optimization!
For documentation purpose, the link to a similar implementation in the mongo scala driver: https://github.com/mongodb/mongo-scala-driver/blob/76dad47c8dbfc98b59867355a966cf95ef72e556/bson/src/main/scala/org/mongodb/scala/bson/DefaultHelper.scala
Very nice. I just added this to a much-used utility we have and it worked like a charm. Thanks!